From 12bd4897ff0678fa663e09d78ebc22dd255ceb86 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Mon, 9 Feb 2015 01:44:09 +0000 Subject: [PATCH 1/2] Import LLDB as of upstream SVN 228549 (git 39760838) --- include/lldb/API/SBLaunchInfo.h | 186 ++ include/lldb/API/SBPlatform.h | 13 + include/lldb/API/SBTarget.h | 161 +- include/lldb/API/SBType.h | 6 + include/lldb/Breakpoint/Breakpoint.h | 18 +- include/lldb/Breakpoint/BreakpointLocation.h | 4 + include/lldb/Breakpoint/StoppointLocation.h | 3 + include/lldb/Core/ArchSpec.h | 15 + include/lldb/Core/Broadcaster.h | 7 +- include/lldb/Core/Connection.h | 22 +- include/lldb/Core/ConnectionMachPort.h | 4 + include/lldb/Core/ConnectionSharedMemory.h | 3 + include/lldb/Core/Debugger.h | 26 +- include/lldb/Core/Disassembler.h | 6 +- include/lldb/Core/FormatEntity.h | 260 ++ include/lldb/Core/Mangled.h | 19 + include/lldb/Core/Module.h | 16 +- include/lldb/Core/RegularExpression.h | 41 +- include/lldb/Core/ValueObject.h | 12 +- .../lldb/Core/ValueObjectSyntheticFilter.h | 3 + include/lldb/DataFormatters/TypeSummary.h | 30 +- .../lldb/Expression/ASTResultSynthesizer.h | 2 +- include/lldb/Expression/ASTStructExtractor.h | 2 +- include/lldb/Expression/IRExecutionUnit.h | 10 +- include/lldb/Host/File.h | 3 +- include/lldb/Host/Host.h | 3 - include/lldb/Host/PipeBase.h | 2 + include/lldb/Host/Socket.h | 31 +- include/lldb/Host/SocketAddress.h | 7 + include/lldb/Host/StringConvert.h | 45 + .../lldb}/Host/common/NativeBreakpoint.h | 0 .../lldb}/Host/common/NativeBreakpointList.h | 0 .../lldb}/Host/common/NativeProcessProtocol.h | 5 + .../common}/NativeRegisterContext.h | 7 + .../NativeRegisterContextRegisterInfo.h | 3 + .../lldb}/Host/common/NativeThreadProtocol.h | 5 +- .../lldb/Host/common/NativeWatchpointList.h | 47 + .../lldb}/Host/common/SoftwareBreakpoint.h | 0 .../posix/ConnectionFileDescriptorPosix.h | 6 +- include/lldb/Host/posix/PipePosix.h | 2 + include/lldb/Interpreter/Args.h | 12 - include/lldb/Interpreter/CommandInterpreter.h | 9 + .../lldb/Interpreter/OptionGroupPlatform.h | 6 +- include/lldb/Interpreter/OptionValue.h | 15 +- .../Interpreter/OptionValueFormatEntity.h | 107 + .../lldb/Interpreter/OptionValueProperties.h | 4 + include/lldb/Interpreter/OptionValueRegex.h | 8 +- include/lldb/Interpreter/OptionValues.h | 1 + include/lldb/Interpreter/ScriptInterpreter.h | 16 +- .../Interpreter/ScriptInterpreterPython.h | 194 +- include/lldb/Symbol/ClangASTType.h | 8 +- include/lldb/Symbol/ObjectFile.h | 17 + include/lldb/Symbol/SymbolContext.h | 1 + include/lldb/Target/FileAction.h | 2 +- include/lldb/Target/LanguageRuntime.h | 7 + include/lldb/Target/ObjCLanguageRuntime.h | 7 + include/lldb/Target/Platform.h | 30 +- include/lldb/Target/Process.h | 6 +- include/lldb/Utility/AnsiTerminal.h | 31 - include/lldb/Utility/ProcessStructReader.h | 4 +- include/lldb/lldb-enumerations.h | 11 +- include/lldb/lldb-forward.h | 1 + source/API/SBInstruction.cpp | 10 +- source/API/SBInstructionList.cpp | 5 +- source/API/SBLaunchInfo.cpp | 278 ++ source/API/SBPlatform.cpp | 159 +- source/API/SBStream.cpp | 6 + source/API/SBTarget.cpp | 256 +- source/API/SBThread.cpp | 3 +- source/API/SBType.cpp | 25 +- source/API/SBTypeCategory.cpp | 4 +- source/API/SBValue.cpp | 3 +- source/Breakpoint/Breakpoint.cpp | 8 +- source/Breakpoint/BreakpointLocation.cpp | 15 + source/Breakpoint/StoppointLocation.cpp | 7 + source/Commands/CommandObjectBreakpoint.cpp | 20 +- source/Commands/CommandObjectDisassemble.cpp | 6 +- source/Commands/CommandObjectExpression.cpp | 4 +- source/Commands/CommandObjectFrame.cpp | 5 +- source/Commands/CommandObjectGUI.cpp | 20 +- source/Commands/CommandObjectHelp.cpp | 20 +- source/Commands/CommandObjectHelp.h | 11 +- source/Commands/CommandObjectLog.cpp | 3 +- source/Commands/CommandObjectMemory.cpp | 21 +- source/Commands/CommandObjectPlatform.cpp | 42 +- source/Commands/CommandObjectProcess.cpp | 229 +- source/Commands/CommandObjectSource.cpp | 8 +- source/Commands/CommandObjectTarget.cpp | 149 +- source/Commands/CommandObjectThread.cpp | 115 +- source/Commands/CommandObjectWatchpoint.cpp | 3 +- source/Core/Address.cpp | 4 +- source/Core/ArchSpec.cpp | 13 + source/Core/Broadcaster.cpp | 10 + source/Core/ConnectionMachPort.cpp | 8 + source/Core/ConnectionSharedMemory.cpp | 7 + source/Core/ConstString.cpp | 2 +- source/Core/Debugger.cpp | 1750 +----------- source/Core/Disassembler.cpp | 45 +- source/Core/Error.cpp | 2 +- source/Core/FormatEntity.cpp | 2511 +++++++++++++++++ source/Core/IOHandler.cpp | 28 +- source/Core/Log.cpp | 4 - source/Core/Mangled.cpp | 44 +- source/Core/Module.cpp | 25 +- source/Core/RegisterValue.cpp | 5 +- source/Core/RegularExpression.cpp | 56 +- source/Core/Scalar.cpp | 5 +- source/Core/StreamFile.cpp | 3 +- source/Core/Value.cpp | 4 +- source/Core/ValueObject.cpp | 75 +- source/Core/ValueObjectConstResult.cpp | 4 +- source/Core/ValueObjectDynamicValue.cpp | 2 +- source/Core/ValueObjectMemory.cpp | 2 +- source/Core/ValueObjectSyntheticFilter.cpp | 6 + source/Core/ValueObjectVariable.cpp | 4 +- .../DataFormatters/CXXFormatterFunctions.cpp | 2 +- source/DataFormatters/FormatManager.cpp | 2 + source/DataFormatters/LibCxx.cpp | 5 +- .../DataFormatters/LibCxxInitializerList.cpp | 2 +- source/DataFormatters/LibCxxVector.cpp | 2 +- source/DataFormatters/TypeSummary.cpp | 36 +- source/DataFormatters/TypeSynthetic.cpp | 24 +- source/Expression/ASTResultSynthesizer.cpp | 4 +- source/Expression/ASTStructExtractor.cpp | 4 +- source/Expression/ClangExpressionParser.cpp | 1 - source/Expression/ClangModulesDeclVendor.cpp | 8 +- source/Expression/ExpressionSourceCode.cpp | 6 +- source/Expression/IRExecutionUnit.cpp | 165 +- source/Expression/IRForTarget.cpp | 6 +- source/Expression/Materializer.cpp | 4 +- source/Host/common/Editline.cpp | 21 + source/Host/common/File.cpp | 9 +- source/Host/common/FileSpec.cpp | 11 +- source/Host/common/Host.cpp | 21 +- source/Host/common/HostInfoBase.cpp | 269 +- source/Host/common/NativeBreakpoint.cpp | 2 +- source/Host/common/NativeBreakpointList.cpp | 6 +- source/Host/common/NativeProcessProtocol.cpp | 30 +- .../common}/NativeRegisterContext.cpp | 12 +- .../NativeRegisterContextRegisterInfo.cpp | 8 +- source/Host/common/NativeThreadProtocol.cpp | 30 +- source/Host/common/NativeWatchpointList.cpp | 35 + source/Host/common/Socket.cpp | 70 +- source/Host/common/SocketAddress.cpp | 72 + source/Host/common/SoftwareBreakpoint.cpp | 4 +- source/Host/common/StringConvert.cpp | 93 + source/Host/common/ThreadLauncher.cpp | 10 + .../posix/ConnectionFileDescriptorPosix.cpp | 53 +- source/Host/posix/PipePosix.cpp | 35 + source/Interpreter/Args.cpp | 96 +- source/Interpreter/CommandHistory.cpp | 8 +- source/Interpreter/CommandInterpreter.cpp | 172 +- .../Interpreter/CommandObjectRegexCommand.cpp | 2 +- source/Interpreter/OptionGroupPlatform.cpp | 35 + .../OptionGroupValueObjectDisplay.cpp | 7 +- source/Interpreter/OptionValue.cpp | 45 +- source/Interpreter/OptionValueArray.cpp | 9 +- .../Interpreter/OptionValueFileSpecLIst.cpp | 7 +- .../Interpreter/OptionValueFormatEntity.cpp | 124 + .../Interpreter/OptionValuePathMappings.cpp | 7 +- source/Interpreter/OptionValueProperties.cpp | 12 + source/Interpreter/OptionValueRegex.cpp | 4 +- source/Interpreter/OptionValueSInt64.cpp | 4 +- source/Interpreter/OptionValueUInt64.cpp | 4 +- source/Interpreter/Property.cpp | 41 +- .../Interpreter/ScriptInterpreterPython.cpp | 59 +- .../Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 6 +- .../ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp | 10 +- .../ABI/MacOSX-i386/ABIMacOSX_i386.cpp | 21 +- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp | 20 +- .../Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp | 20 +- .../ABI/SysV-x86_64/ABISysV_x86_64.cpp | 27 +- .../Disassembler/llvm/DisassemblerLLVMC.cpp | 4 +- .../POSIX-DYLD/DYLDRendezvous.cpp | 32 +- .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.h | 3 + .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 3 + .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 3 +- .../Plugins/Platform/POSIX/PlatformPOSIX.cpp | 84 +- .../gdb-server/PlatformRemoteGDBServer.cpp | 146 +- .../gdb-server/PlatformRemoteGDBServer.h | 6 +- .../Process/FreeBSD/ProcessMonitor.cpp | 183 +- .../Plugins/Process/FreeBSD/ProcessMonitor.h | 15 +- source/Plugins/Process/POSIX/CrashReason.cpp | 315 +++ source/Plugins/Process/POSIX/CrashReason.h | 62 + .../Plugins/Process/POSIX/POSIXStopInfo.cpp | 15 +- source/Plugins/Process/POSIX/POSIXStopInfo.h | 22 +- .../Plugins/Process/POSIX/ProcessMessage.cpp | 190 +- source/Plugins/Process/POSIX/ProcessMessage.h | 51 +- source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 11 +- ...sterContextPOSIXProcessMonitor_powerpc.cpp | 53 +- ...gisterContextPOSIXProcessMonitor_powerpc.h | 9 + .../Process/Utility/DynamicRegisterInfo.cpp | 6 +- .../RegisterContextFreeBSD_powerpc.cpp | 39 + .../Process/Utility/RegisterContextLLDB.cpp | 7 +- .../Utility/RegisterContextLinux_i386.cpp | 5 + .../Utility/RegisterContextLinux_i386.h | 3 + .../Utility/RegisterContextLinux_x86_64.cpp | 24 +- .../Utility/RegisterContextLinux_x86_64.h | 4 + .../Utility/RegisterContextPOSIX_powerpc.cpp | 51 +- .../Utility/RegisterContextPOSIX_powerpc.h | 45 + .../Process/Utility/RegisterContext_powerpc.h | 79 +- .../Process/Utility/RegisterInfoInterface.h | 11 + .../Process/Utility/RegisterInfos_powerpc.h | 42 +- .../Process/Utility/lldb-x86-register-enums.h | 6 +- .../Process/elf-core/ProcessElfCore.cpp | 6 +- .../RegisterContextPOSIXCore_powerpc.cpp | 29 +- .../RegisterContextPOSIXCore_powerpc.h | 11 +- .../Process/elf-core/ThreadElfCore.cpp | 5 +- .../Plugins/Process/elf-core/ThreadElfCore.h | 2 + .../gdb-remote/GDBRemoteCommunication.cpp | 49 +- .../gdb-remote/GDBRemoteCommunication.h | 13 +- .../GDBRemoteCommunicationClient.cpp | 86 +- .../gdb-remote/GDBRemoteCommunicationClient.h | 32 +- .../GDBRemoteCommunicationServer.cpp | 418 ++- .../gdb-remote/GDBRemoteCommunicationServer.h | 8 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 62 +- .../SymbolFile/DWARF/DWARFCompileUnit.cpp | 7 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 32 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 147 +- .../SymbolFile/DWARF/SymbolFileDWARF.h | 7 + .../UnwindAssemblyInstEmulation.cpp | 6 +- source/Symbol/ClangASTContext.cpp | 4 +- source/Symbol/ClangASTType.cpp | 106 +- source/Symbol/CompactUnwindInfo.cpp | 29 +- source/Symbol/SymbolContext.cpp | 68 +- source/Symbol/Type.cpp | 16 +- source/Symbol/Variable.cpp | 3 + source/Target/ExecutionContext.cpp | 6 +- source/Target/LanguageRuntime.cpp | 3 + source/Target/ObjCLanguageRuntime.cpp | 46 +- source/Target/Platform.cpp | 85 +- source/Target/Process.cpp | 10 +- source/Target/ProcessLaunchInfo.cpp | 9 +- source/Target/StackFrame.cpp | 5 +- source/Target/StopInfo.cpp | 5 + source/Target/TargetList.cpp | 48 +- source/Target/Thread.cpp | 23 +- source/Target/ThreadPlanTracer.cpp | 2 +- source/Target/UnixSignals.cpp | 4 +- source/Utility/StringExtractorGDBRemote.cpp | 3 + source/Utility/StringExtractorGDBRemote.h | 1 + source/Utility/UriParser.cpp | 21 +- source/Utility/UriParser.h | 8 + tools/compact-unwind/compact-unwind-dumper.c | 50 +- tools/lldb-mi/Driver.cpp | 22 +- tools/lldb-mi/Driver.h | 10 +- tools/lldb-mi/MICmdArgValConsume.cpp | 29 +- tools/lldb-mi/MICmdCmd.h | 4 +- tools/lldb-mi/MICmdCmdBreak.cpp | 45 +- tools/lldb-mi/MICmdCmdBreak.h | 2 +- tools/lldb-mi/MICmdCmdData.cpp | 255 +- tools/lldb-mi/MICmdCmdData.h | 7 +- tools/lldb-mi/MICmdCmdExec.cpp | 49 +- tools/lldb-mi/MICmdCmdExec.h | 2 +- tools/lldb-mi/MICmdCmdFile.cpp | 6 +- tools/lldb-mi/MICmdCmdGdbInfo.cpp | 10 +- tools/lldb-mi/MICmdCmdMiscellanous.cpp | 34 +- tools/lldb-mi/MICmdCmdMiscellanous.h | 2 +- tools/lldb-mi/MICmdCmdStack.cpp | 103 +- tools/lldb-mi/MICmdCmdStack.h | 10 +- tools/lldb-mi/MICmdCmdTarget.cpp | 21 +- tools/lldb-mi/MICmdCmdThread.cpp | 14 +- tools/lldb-mi/MICmdCmdVar.cpp | 129 +- tools/lldb-mi/MICmdCmdVar.h | 7 +- tools/lldb-mi/MICmnLLDBBroadcaster.h | 2 +- tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp | 393 ++- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h | 43 +- .../lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h | 2 +- tools/lldb-mi/MICmnLLDBDebugger.cpp | 19 +- tools/lldb-mi/MICmnLLDBDebugger.h | 6 +- .../lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp | 87 +- tools/lldb-mi/MICmnLLDBProxySBValue.cpp | 6 +- tools/lldb-mi/MICmnLLDBProxySBValue.h | 2 +- tools/lldb-mi/MICmnLLDBUtilSBValue.cpp | 2 +- tools/lldb-mi/MICmnLLDBUtilSBValue.h | 2 +- tools/lldb-mi/MICmnLog.cpp | 1 - tools/lldb-mi/MICmnResources.cpp | 3 +- tools/lldb-mi/MICmnResources.h | 3 +- tools/lldb-mi/MIDriver.cpp | 11 +- tools/lldb-mi/MIDriverBase.cpp | 4 +- tools/lldb-mi/MIDriverBase.h | 4 +- tools/lldb-mi/MIDriverMain.cpp | 14 +- tools/lldb-mi/MIDriverMgr.cpp | 20 +- tools/lldb-mi/MIDriverMgr.h | 2 +- tools/lldb-mi/MIReadMe.txt | 2 +- 285 files changed, 8928 insertions(+), 4853 deletions(-) create mode 100644 include/lldb/API/SBLaunchInfo.h create mode 100644 include/lldb/Core/FormatEntity.h create mode 100644 include/lldb/Host/StringConvert.h rename {source => include/lldb}/Host/common/NativeBreakpoint.h (100%) rename {source => include/lldb}/Host/common/NativeBreakpointList.h (100%) rename {source => include/lldb}/Host/common/NativeProcessProtocol.h (98%) rename include/lldb/{Target => Host/common}/NativeRegisterContext.h (97%) rename include/lldb/{Target => Host/common}/NativeRegisterContextRegisterInfo.h (95%) rename {source => include/lldb}/Host/common/NativeThreadProtocol.h (93%) create mode 100644 include/lldb/Host/common/NativeWatchpointList.h rename {source => include/lldb}/Host/common/SoftwareBreakpoint.h (100%) create mode 100644 include/lldb/Interpreter/OptionValueFormatEntity.h create mode 100644 source/API/SBLaunchInfo.cpp create mode 100644 source/Core/FormatEntity.cpp rename source/{Target => Host/common}/NativeRegisterContext.cpp (98%) rename source/{Target => Host/common}/NativeRegisterContextRegisterInfo.cpp (87%) create mode 100644 source/Host/common/NativeWatchpointList.cpp create mode 100644 source/Host/common/StringConvert.cpp create mode 100644 source/Interpreter/OptionValueFormatEntity.cpp create mode 100644 source/Plugins/Process/POSIX/CrashReason.cpp create mode 100644 source/Plugins/Process/POSIX/CrashReason.h diff --git a/include/lldb/API/SBLaunchInfo.h b/include/lldb/API/SBLaunchInfo.h new file mode 100644 index 000000000000..a5921ab90d48 --- /dev/null +++ b/include/lldb/API/SBLaunchInfo.h @@ -0,0 +1,186 @@ +//===-- SBLaunchInfo.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBLaunchInfo_h_ +#define LLDB_SBLaunchInfo_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBPlatform; +class SBTarget; + +class SBLaunchInfo +{ +public: + SBLaunchInfo (const char **argv); + + ~SBLaunchInfo(); + + lldb::pid_t + GetProcessID(); + + uint32_t + GetUserID(); + + uint32_t + GetGroupID(); + + bool + UserIDIsValid (); + + bool + GroupIDIsValid (); + + void + SetUserID (uint32_t uid); + + void + SetGroupID (uint32_t gid); + + SBFileSpec + GetExecutableFile (); + + //---------------------------------------------------------------------- + /// Set the executable file that will be used to launch the process and + /// optionally set it as the first argument in the argument vector. + /// + /// This only needs to be specified if clients wish to carefully control + /// the exact path will be used to launch a binary. If you create a + /// target with a symlink, that symlink will get resolved in the target + /// and the resolved path will get used to launch the process. Calling + /// this function can help you still launch your process using the + /// path of your choice. + /// + /// If this function is not called prior to launching with + /// SBTarget::Launch(...), the target will use the resolved executable + /// path that was used to create the target. + /// + /// @param[in] exe_file + /// The override path to use when launching the executable. + /// + /// @param[in] add_as_first_arg + /// If true, then the path will be inserted into the argument vector + /// prior to launching. Otherwise the argument vector will be left + /// alone. + //---------------------------------------------------------------------- + void + SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg); + + + //---------------------------------------------------------------------- + /// Get the listener that will be used to receive process events. + /// + /// If no listener has been set via a call to + /// SBLaunchInfo::SetListener(), then an invalid SBListener will be + /// returned (SBListener::IsValid() will return false). If a listener + /// has been set, then the valid listener object will be returned. + //---------------------------------------------------------------------- + SBListener + GetListener (); + + //---------------------------------------------------------------------- + /// Set the listener that will be used to receive process events. + /// + /// By default the SBDebugger, which has a listener, that the SBTarget + /// belongs to will listen for the process events. Calling this function + /// allows a different listener to be used to listen for process events. + //---------------------------------------------------------------------- + void + SetListener (SBListener &listener); + + uint32_t + GetNumArguments (); + + const char * + GetArgumentAtIndex (uint32_t idx); + + void + SetArguments (const char **argv, bool append); + + uint32_t + GetNumEnvironmentEntries (); + + const char * + GetEnvironmentEntryAtIndex (uint32_t idx); + + void + SetEnvironmentEntries (const char **envp, bool append); + + void + Clear (); + + const char * + GetWorkingDirectory () const; + + void + SetWorkingDirectory (const char *working_dir); + + uint32_t + GetLaunchFlags (); + + void + SetLaunchFlags (uint32_t flags); + + const char * + GetProcessPluginName (); + + void + SetProcessPluginName (const char *plugin_name); + + const char * + GetShell (); + + void + SetShell (const char * path); + + uint32_t + GetResumeCount (); + + void + SetResumeCount (uint32_t c); + + bool + AddCloseFileAction (int fd); + + bool + AddDuplicateFileAction (int fd, int dup_fd); + + bool + AddOpenFileAction (int fd, const char *path, bool read, bool write); + + bool + AddSuppressFileAction (int fd, bool read, bool write); + + void + SetLaunchEventData (const char *data); + + const char * + GetLaunchEventData () const; + + bool + GetDetachOnError() const; + + void + SetDetachOnError(bool enable); + +protected: + friend class SBPlatform; + friend class SBTarget; + + lldb_private::ProcessLaunchInfo & + ref (); + + ProcessLaunchInfoSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBLaunchInfo_h_ diff --git a/include/lldb/API/SBPlatform.h b/include/lldb/API/SBPlatform.h index 16a546d81f9b..42b2d0492895 100644 --- a/include/lldb/API/SBPlatform.h +++ b/include/lldb/API/SBPlatform.h @@ -12,11 +12,15 @@ #include "lldb/API/SBDefines.h" +#include + struct PlatformConnectOptions; struct PlatformShellCommand; namespace lldb { + class SBLaunchInfo; + class SBPlatformConnectOptions { public: @@ -170,6 +174,12 @@ namespace lldb { SBError Run (SBPlatformShellCommand &shell_command); + SBError + Launch (SBLaunchInfo &launch_info); + + SBError + Kill (const lldb::pid_t pid); + SBError MakeDirectory (const char *path, uint32_t file_permissions = eFilePermissionsDirectoryDefault); @@ -190,6 +200,9 @@ namespace lldb { void SetSP (const lldb::PlatformSP& platform_sp); + SBError + ExecuteConnected (const std::function& func); + lldb::PlatformSP m_opaque_sp; }; diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h index a628467caa43..322cf04159ff 100644 --- a/include/lldb/API/SBTarget.h +++ b/include/lldb/API/SBTarget.h @@ -15,6 +15,7 @@ #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBFileSpecList.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBSymbolContextList.h" #include "lldb/API/SBType.h" #include "lldb/API/SBValue.h" @@ -24,166 +25,6 @@ namespace lldb { class SBPlatform; -class SBLaunchInfo -{ -public: - SBLaunchInfo (const char **argv); - - ~SBLaunchInfo(); - - uint32_t - GetUserID(); - - uint32_t - GetGroupID(); - - bool - UserIDIsValid (); - - bool - GroupIDIsValid (); - - void - SetUserID (uint32_t uid); - - void - SetGroupID (uint32_t gid); - - SBFileSpec - GetExecutableFile (); - - //---------------------------------------------------------------------- - /// Set the executable file that will be used to launch the process and - /// optionally set it as the first argument in the argument vector. - /// - /// This only needs to be specified if clients wish to carefully control - /// the exact path will be used to launch a binary. If you create a - /// target with a symlink, that symlink will get resolved in the target - /// and the resolved path will get used to launch the process. Calling - /// this function can help you still launch your process using the - /// path of your choice. - /// - /// If this function is not called prior to launching with - /// SBTarget::Launch(...), the target will use the resolved executable - /// path that was used to create the target. - /// - /// @param[in] exe_file - /// The override path to use when launching the executable. - /// - /// @param[in] add_as_first_arg - /// If true, then the path will be inserted into the argument vector - /// prior to launching. Otherwise the argument vector will be left - /// alone. - //---------------------------------------------------------------------- - void - SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg); - - - //---------------------------------------------------------------------- - /// Get the listener that will be used to receive process events. - /// - /// If no listener has been set via a call to - /// SBLaunchInfo::SetListener(), then an invalid SBListener will be - /// returned (SBListener::IsValid() will return false). If a listener - /// has been set, then the valid listener object will be returned. - //---------------------------------------------------------------------- - SBListener - GetListener (); - - //---------------------------------------------------------------------- - /// Set the listener that will be used to receive process events. - /// - /// By default the SBDebugger, which has a listener, that the SBTarget - /// belongs to will listen for the process events. Calling this function - /// allows a different listener to be used to listen for process events. - //---------------------------------------------------------------------- - void - SetListener (SBListener &listener); - - uint32_t - GetNumArguments (); - - const char * - GetArgumentAtIndex (uint32_t idx); - - void - SetArguments (const char **argv, bool append); - - uint32_t - GetNumEnvironmentEntries (); - - const char * - GetEnvironmentEntryAtIndex (uint32_t idx); - - void - SetEnvironmentEntries (const char **envp, bool append); - - void - Clear (); - - const char * - GetWorkingDirectory () const; - - void - SetWorkingDirectory (const char *working_dir); - - uint32_t - GetLaunchFlags (); - - void - SetLaunchFlags (uint32_t flags); - - const char * - GetProcessPluginName (); - - void - SetProcessPluginName (const char *plugin_name); - - const char * - GetShell (); - - void - SetShell (const char * path); - - uint32_t - GetResumeCount (); - - void - SetResumeCount (uint32_t c); - - bool - AddCloseFileAction (int fd); - - bool - AddDuplicateFileAction (int fd, int dup_fd); - - bool - AddOpenFileAction (int fd, const char *path, bool read, bool write); - - bool - AddSuppressFileAction (int fd, bool read, bool write); - - void - SetLaunchEventData (const char *data); - - const char * - GetLaunchEventData () const; - - bool - GetDetachOnError() const; - - void - SetDetachOnError(bool enable); - -protected: - friend class SBTarget; - - lldb_private::ProcessLaunchInfo & - ref (); - - ProcessLaunchInfoSP m_opaque_sp; -}; - class SBAttachInfo { public: diff --git a/include/lldb/API/SBType.h b/include/lldb/API/SBType.h index 303ddff6dc09..7990fc0696a9 100644 --- a/include/lldb/API/SBType.h +++ b/include/lldb/API/SBType.h @@ -152,6 +152,9 @@ class SBType bool IsArrayType (); + bool + IsVectorType (); + bool IsTypedefType (); @@ -175,6 +178,9 @@ class SBType lldb::SBType GetArrayElementType (); + + lldb::SBType + GetVectorElementType (); lldb::SBType GetCanonicalType(); diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h index 61acc061aebc..883571a3ce9a 100644 --- a/include/lldb/Breakpoint/Breakpoint.h +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -714,6 +714,19 @@ class Breakpoint: bool IgnoreCountShouldStop (); + void + IncrementHitCount() + { + m_hit_count++; + } + + void + DecrementHitCount() + { + assert (m_hit_count > 0); + m_hit_count--; + } + private: // This one should only be used by Target to copy breakpoints from target to target - primarily from the dummy // target to prime new targets. @@ -733,7 +746,10 @@ class Breakpoint: BreakpointLocationList m_locations; // The list of locations currently found for this breakpoint. std::string m_kind_description; bool m_resolve_indirect_symbols; - + uint32_t m_hit_count; // Number of times this breakpoint/watchpoint has been hit. This is kept + // separately from the locations hit counts, since locations can go away when + // their backing library gets unloaded, and we would lose hit counts. + void SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind); diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h index 8d5ebce411df..642256386785 100644 --- a/include/lldb/Breakpoint/BreakpointLocation.h +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -390,6 +390,7 @@ class BreakpointLocation : friend class BreakpointSite; friend class BreakpointLocationList; friend class Process; + friend class StopInfoBreakpoint; //------------------------------------------------------------------ /// Set the breakpoint site for this location to \a bp_site_sp. @@ -417,6 +418,9 @@ class BreakpointLocation : void BumpHitCount(); + void + UndoBumpHitCount(); + //------------------------------------------------------------------ // Constructors and Destructors diff --git a/include/lldb/Breakpoint/StoppointLocation.h b/include/lldb/Breakpoint/StoppointLocation.h index 452c6388c82d..32a1dbd4386e 100644 --- a/include/lldb/Breakpoint/StoppointLocation.h +++ b/include/lldb/Breakpoint/StoppointLocation.h @@ -134,6 +134,9 @@ class StoppointLocation ++m_hit_count; } + void + DecrementHitCount (); + private: //------------------------------------------------------------------ // For StoppointLocation only diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 694e204cdc0d..93630f043822 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -276,6 +276,21 @@ class ArchSpec return !m_triple.getOSName().empty(); } + //------------------------------------------------------------------ + /// Merges fields from another ArchSpec into this ArchSpec. + /// + /// This will use the supplied ArchSpec to fill in any fields of + /// the triple in this ArchSpec which were unspecified. This can + /// be used to refine a generic ArchSpec with a more specific one. + /// For example, if this ArchSpec's triple is something like + /// i386-unknown-unknown-unknown, and we have a triple which is + /// x64-pc-windows-msvc, then merging that triple into this one + /// will result in the triple i386-pc-windows-msvc. + /// + //------------------------------------------------------------------ + void + MergeFrom(const ArchSpec &other); + //------------------------------------------------------------------ /// Sets this ArchSpec according to the given architecture name. /// diff --git a/include/lldb/Core/Broadcaster.h b/include/lldb/Core/Broadcaster.h index 64b12ca8a938..6d54b1b43133 100644 --- a/include/lldb/Core/Broadcaster.h +++ b/include/lldb/Core/Broadcaster.h @@ -419,12 +419,7 @@ class Broadcaster HijackBroadcaster (Listener *listener, uint32_t event_mask = UINT32_MAX); bool - IsHijackedForEvent (uint32_t event_mask) - { - if (m_hijacking_listeners.size() > 0) - return (event_mask & m_hijacking_masks.back()) != 0; - return false; - } + IsHijackedForEvent (uint32_t event_mask); //------------------------------------------------------------------ /// Restore the state of the Broadcaster from a previous hijack attempt. diff --git a/include/lldb/Core/Connection.h b/include/lldb/Core/Connection.h index 775e0c846f85..a7b911ac382f 100644 --- a/include/lldb/Core/Connection.h +++ b/include/lldb/Core/Connection.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -133,13 +134,13 @@ class Connection /// /// Subclasses must override this function. /// - /// @param[in] src - /// A source buffer that must be at least \a src_len bytes + /// @param[in] dst + /// A desination buffer that must be at least \a dst_len bytes /// long. /// - /// @param[in] src_len + /// @param[in] dst_len /// The number of bytes to attempt to write, and also the - /// number of bytes are currently available in \a src. + /// number of bytes are currently available in \a dst. /// /// @param[out] error_ptr /// A pointer to an error object that should be given an @@ -150,7 +151,18 @@ class Connection /// The number of bytes actually Written. //------------------------------------------------------------------ virtual size_t - Write (const void *buffer, size_t length, lldb::ConnectionStatus &status, Error *error_ptr) = 0; + Write (const void *dst, size_t dst_len, lldb::ConnectionStatus &status, Error *error_ptr) = 0; + + //------------------------------------------------------------------ + /// Returns a URI that describes this connection object + /// + /// Subclasses may override this function. + /// + /// @return + /// Returns URI or an empty string if disconnecteds + //------------------------------------------------------------------ + virtual std::string + GetURI() = 0; private: //------------------------------------------------------------------ diff --git a/include/lldb/Core/ConnectionMachPort.h b/include/lldb/Core/ConnectionMachPort.h index 04ec7f69136b..78eb78cb95f4 100644 --- a/include/lldb/Core/ConnectionMachPort.h +++ b/include/lldb/Core/ConnectionMachPort.h @@ -56,6 +56,9 @@ class ConnectionMachPort : lldb::ConnectionStatus &status, lldb_private::Error *error_ptr); + virtual std::string + GetURI(); + lldb::ConnectionStatus BootstrapCheckIn (const char *port_name, lldb_private::Error *error_ptr); @@ -83,6 +86,7 @@ class ConnectionMachPort : mach_port_t m_port; private: + std::string m_uri; DISALLOW_COPY_AND_ASSIGN (ConnectionMachPort); diff --git a/include/lldb/Core/ConnectionSharedMemory.h b/include/lldb/Core/ConnectionSharedMemory.h index 0f9cdcb8a92d..48e62142954e 100644 --- a/include/lldb/Core/ConnectionSharedMemory.h +++ b/include/lldb/Core/ConnectionSharedMemory.h @@ -53,6 +53,9 @@ class ConnectionSharedMemory : virtual size_t Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + virtual std::string + GetURI(); + lldb::ConnectionStatus Open (bool create, const char *name, size_t size, Error *error_ptr); diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h index 15c832f4bf66..9a3f9736fdca 100644 --- a/include/lldb/Core/Debugger.h +++ b/include/lldb/Core/Debugger.h @@ -19,6 +19,7 @@ #include "lldb/lldb-public.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Communication.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/Listener.h" #include "lldb/Core/SourceManager.h" @@ -158,8 +159,6 @@ friend class SourceManager; // For GetSourceFileCache. // To get the target's source manager, call GetSourceManager on the target instead. SourceManager & GetSourceManager (); - -public: lldb::TargetSP GetSelectedTarget () @@ -224,6 +223,12 @@ friend class SourceManager; // For GetSourceFileCache. ConstString GetTopIOHandlerControlSequence(char ch); + const char * + GetIOHandlerCommandPrefix(); + + const char * + GetIOHandlerHelpPrologue(); + bool HideTopIOHandler(); @@ -243,15 +248,7 @@ friend class SourceManager; // For GetSourceFileCache. GetDebuggerAtIndex (size_t index); static bool - FormatPrompt (const char *format, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s, - ValueObject* valobj = NULL); - - static bool - FormatDisassemblerAddress (const char *format, + FormatDisassemblerAddress (const FormatEntity::Entry *format, const SymbolContext *sc, const SymbolContext *prev_sc, const ExecutionContext *exe_ctx, @@ -296,13 +293,13 @@ friend class SourceManager; // For GetSourceFileCache. bool GetAutoConfirm () const; - const char * + const FormatEntity::Entry * GetDisassemblyFormat() const; - const char * + const FormatEntity::Entry * GetFrameFormat() const; - const char * + const FormatEntity::Entry * GetThreadFormat() const; lldb::ScriptLanguage @@ -352,7 +349,6 @@ friend class SourceManager; // For GetSourceFileCache. bool GetNotifyVoid () const; - const ConstString & GetInstanceName() diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h index b0b841b0a925..64d35e67bfd0 100644 --- a/include/lldb/Core/Disassembler.h +++ b/include/lldb/Core/Disassembler.h @@ -117,7 +117,7 @@ class Instruction /// the InstructionList. /// Only needed if show_address is true. /// - /// @param[in] disassembly_addr_format_spec + /// @param[in] disassembly_addr_format /// The format specification for how addresses are printed. /// Only needed if show_address is true. //------------------------------------------------------------------ @@ -130,7 +130,7 @@ class Instruction const ExecutionContext* exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, - const char *disassembly_addr_format_spec); + const FormatEntity::Entry *disassembly_addr_format); virtual bool DoesBranch () = 0; @@ -457,7 +457,7 @@ class Disassembler : //------------------------------------------------------------------ // Classes that inherit from Disassembler can see and modify these //------------------------------------------------------------------ - const ArchSpec m_arch; + ArchSpec m_arch; InstructionList m_instruction_list; lldb::addr_t m_base_addr; std::string m_flavor; diff --git a/include/lldb/Core/FormatEntity.h b/include/lldb/Core/FormatEntity.h new file mode 100644 index 000000000000..32ff9ea4e3eb --- /dev/null +++ b/include/lldb/Core/FormatEntity.h @@ -0,0 +1,260 @@ +//===-- FormatEntity.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_FormatEntity_h_ +#define liblldb_FormatEntity_h_ +#if defined(__cplusplus) + +#include +#include + +#include "lldb/lldb-private.h" +#include "lldb/Core/Error.h" + +namespace llvm +{ + class StringRef; +} + +namespace lldb_private +{ + class FormatEntity + { + public: + struct Entry + { + enum class Type { + Invalid, + ParentNumber, + ParentString, + InsertString, + Root, + String, + Scope, + Variable, + VariableSynthetic, + ScriptVariable, + ScriptVariableSynthetic, + AddressLoad, + AddressFile, + AddressLoadOrFile, + ProcessID, + ProcessFile, + ScriptProcess, + ThreadID, + ThreadProtocolID, + ThreadIndexID, + ThreadName, + ThreadQueue, + ThreadStopReason, + ThreadReturnValue, + ThreadCompletedExpression, + ScriptThread, + ThreadInfo, + TargetArch, + ScriptTarget, + ModuleFile, + File, + FrameIndex, + FrameRegisterPC, + FrameRegisterSP, + FrameRegisterFP, + FrameRegisterFlags, + FrameRegisterByName, + ScriptFrame, + FunctionID, + FunctionDidChange, + FunctionInitialFunction, + FunctionName, + FunctionNameWithArgs, + FunctionNameNoArgs, + FunctionAddrOffset, + FunctionAddrOffsetConcrete, + FunctionLineOffset, + FunctionPCOffset, + LineEntryFile, + LineEntryLineNumber, + LineEntryStartAddress, + LineEntryEndAddress, + CurrentPCArrow + }; + + enum FormatType + { + None, + UInt32, + UInt64, + CString + }; + + struct Definition + { + const char *name; + const char *string; // Insert this exact string into the output + Entry::Type type; + FormatType format_type; // uint32_t, uint64_t, cstr, or anything that can be formatted by printf or lldb::Format + uint64_t data; + uint32_t num_children; + Definition *children; // An array of "num_children" Definition entries, + bool keep_separator; + }; + + Entry (Type t = Type::Invalid, + const char *s = NULL, + const char *f = NULL) : + string (s ? s : ""), + printf_format (f ? f : ""), + children (), + definition (NULL), + type (t), + fmt (lldb::eFormatDefault), + number (0), + deref (false) + { + } + + Entry (llvm::StringRef s); + Entry (char ch); + + void + AppendChar (char ch); + + void + AppendText (const llvm::StringRef &s); + + void + AppendText (const char *cstr); + + void + AppendEntry (const Entry &&entry) + { + children.push_back(entry); + } + + void + Clear () + { + string.clear(); + printf_format.clear(); + children.clear(); + definition = NULL; + type = Type::Invalid; + fmt = lldb::eFormatDefault; + number = 0; + deref = false; + } + + static const char * + TypeToCString (Type t); + + void + Dump (Stream &s, int depth = 0) const; + + bool + operator == (const Entry &rhs) const + { + if (string != rhs.string) + return false; + if (printf_format != rhs.printf_format) + return false; + const size_t n = children.size(); + const size_t m = rhs.children.size(); + for (size_t i=0; i < std::min(n, m); ++i) + { + if (!(children[i] == rhs.children[i])) + return false; + } + if (children != rhs.children) + return false; + if (definition != rhs.definition) + return false; + if (type != rhs.type) + return false; + if (fmt != rhs.fmt) + return false; + if (deref != rhs.deref) + return false; + return true; + } + + std::string string; + std::string printf_format; + std::vector children; + Definition *definition; + Type type; + lldb::Format fmt; + lldb::addr_t number; + bool deref; + }; + + static bool + Format (const Entry &entry, + Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + ValueObject* valobj, + bool function_changed, + bool initial_function); + + static bool + FormatStringRef (const llvm::StringRef &format, + Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + ValueObject* valobj, + bool function_changed, + bool initial_function); + + static bool + FormatCString (const char *format, + Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + ValueObject* valobj, + bool function_changed, + bool initial_function); + + static Error + Parse (const llvm::StringRef &format, Entry &entry); + + static Error + ExtractVariableInfo (llvm::StringRef &format_str, + llvm::StringRef &variable_name, + llvm::StringRef &variable_format); + + static size_t + AutoComplete (const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //---------------------------------------------------------------------- + // Format the current elements into the stream \a s. + // + // The root element will be stripped off and the format str passed in + // will be either an empty string (print a description of this object), + // or contain a . separated series like a domain name that identifies + // further sub elements to display. + //---------------------------------------------------------------------- + static bool + FormatFileSpec (const FileSpec &file, Stream &s, llvm::StringRef elements, llvm::StringRef element_format); + protected: + + static Error + ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth); + + }; + +} +#endif // #if defined(__cplusplus) +#endif // liblldb_FormatEntity_h_ diff --git a/include/lldb/Core/Mangled.h b/include/lldb/Core/Mangled.h index 2f3df6afd8dc..87b23799882f 100644 --- a/include/lldb/Core/Mangled.h +++ b/include/lldb/Core/Mangled.h @@ -290,6 +290,25 @@ class Mangled void SetValue (const ConstString &name); + //---------------------------------------------------------------------- + /// Get the language only if it is definitive what the language is from + /// the mangling. + /// + /// For a mangled name to have a language it must have both a mangled + /// and a demangled name and it must be definitive from the mangling + /// what the language is. + /// + /// Standard C function names will return eLanguageTypeUnknown because + /// they aren't mangled and it isn't clear what language the name + /// represents (there will be no mangled name). + /// + /// @return + /// The language for the mangled/demangled name, eLanguageTypeUnknown + /// if there is no mangled or demangled counterpart. + //---------------------------------------------------------------------- + lldb::LanguageType + GetLanguage (); + private: //---------------------------------------------------------------------- /// Mangled member variables. diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h index bfde7cbc5db9..60fbb989502e 100644 --- a/include/lldb/Core/Module.h +++ b/include/lldb/Core/Module.h @@ -941,17 +941,8 @@ class Module : const ConstString &object_name); bool - GetIsDynamicLinkEditor () const - { - return m_is_dynamic_loader_module; - } - - void - SetIsDynamicLinkEditor (bool b) - { - m_is_dynamic_loader_module = b; - } - + GetIsDynamicLinkEditor (); + ClangASTContext & GetClangASTContext (); @@ -1124,8 +1115,7 @@ class Module : bool m_did_load_objfile:1, m_did_load_symbol_vendor:1, m_did_parse_uuid:1, - m_did_init_ast:1, - m_is_dynamic_loader_module:1; + m_did_init_ast:1; mutable bool m_file_has_changed:1, m_first_file_changed_log:1; /// See if the module was modified after it was initially opened. diff --git a/include/lldb/Core/RegularExpression.h b/include/lldb/Core/RegularExpression.h index 00d8310b4806..a58d17b4a794 100644 --- a/include/lldb/Core/RegularExpression.h +++ b/include/lldb/Core/RegularExpression.h @@ -121,23 +121,6 @@ class RegularExpression //------------------------------------------------------------------ RegularExpression (); - //------------------------------------------------------------------ - /// Constructor that takes a regular expression with flags. - /// - /// Constructor that compiles \a re using \a flags and stores the - /// resulting compiled regular expression into this object. - /// - /// @param[in] re - /// A c string that represents the regular expression to - /// compile. - /// - /// @param[in] flags - /// Flags that are passed to the \c regcomp() function. - //------------------------------------------------------------------ - explicit - RegularExpression (const char* re, int flags); - - // This one uses flags = REG_EXTENDED. explicit RegularExpression (const char* re); @@ -157,7 +140,7 @@ class RegularExpression /// Compile a regular expression. /// /// Compile a regular expression using the supplied regular - /// expression text and flags. The compiled regular expression lives + /// expression text. The compiled regular expression lives /// in this object so that it can be readily used for regular /// expression matches. Execute() can be called after the regular /// expression is compiled. Any previously compiled regular @@ -167,9 +150,6 @@ class RegularExpression /// A NULL terminated C string that represents the regular /// expression to compile. /// - /// @param[in] flags - /// Flags that are passed to the \c regcomp() function. - /// /// @return /// \b true if the regular expression compiles successfully, /// \b false otherwise. @@ -177,9 +157,6 @@ class RegularExpression bool Compile (const char* re); - bool - Compile (const char* re, int flags); - //------------------------------------------------------------------ /// Executes a regular expression. /// @@ -187,8 +164,7 @@ class RegularExpression /// expression that is already in this object against the match /// string \a s. If any parens are used for regular expression /// matches \a match_count should indicate the number of regmatch_t - /// values that are present in \a match_ptr. The regular expression - /// will be executed using the \a execute_flags + /// values that are present in \a match_ptr. /// /// @param[in] string /// The string to match against the compile regular expression. @@ -198,15 +174,12 @@ class RegularExpression /// properly initialized with the desired number of maximum /// matches, or NULL if no parenthesized matching is needed. /// - /// @param[in] execute_flags - /// Flags to pass to the \c regexec() function. - /// /// @return /// \b true if \a string matches the compiled regular /// expression, \b false otherwise. //------------------------------------------------------------------ bool - Execute (const char* string, Match *match = NULL, int execute_flags = 0) const; + Execute (const char* string, Match *match = NULL) const; size_t GetErrorAsCString (char *err_str, size_t err_str_max_len) const; @@ -233,12 +206,6 @@ class RegularExpression const char* GetText () const; - int - GetCompileFlags () const - { - return m_compile_flags; - } - //------------------------------------------------------------------ /// Test if valid. /// @@ -256,7 +223,6 @@ class RegularExpression { Free(); m_re.clear(); - m_compile_flags = 0; m_comp_err = 1; } @@ -276,7 +242,6 @@ class RegularExpression std::string m_re; ///< A copy of the original regular expression text int m_comp_err; ///< Error code for the regular expression compilation regex_t m_preg; ///< The compiled regular expression - int m_compile_flags; ///< Stores the flags from the last compile. }; } // namespace lldb_private diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h index fa96c8989913..b50adfb69564 100644 --- a/include/lldb/Core/ValueObject.h +++ b/include/lldb/Core/ValueObject.h @@ -527,9 +527,14 @@ class ValueObject : public UserID virtual lldb::ModuleSP GetModule(); - virtual ValueObject* + ValueObject* GetRoot (); + // Given a ValueObject, loop over itself and its parent, and its parent's parent, .. + // until either the given callback returns false, or you end up at a null pointer + ValueObject* + FollowParentChain (std::function); + virtual bool GetDeclaration (Declaration &decl); @@ -875,6 +880,9 @@ class ValueObject : public UserID virtual lldb::LanguageType GetPreferredDisplayLanguage (); + void + SetPreferredDisplayLanguage (lldb::LanguageType); + lldb::TypeSummaryImplSP GetSummaryFormat() { @@ -1106,6 +1114,8 @@ class ValueObject : public UserID llvm::SmallVector m_value_checksum; + lldb::LanguageType m_preferred_display_language; + bool m_value_is_valid:1, m_value_did_change:1, m_children_count_valid:1, diff --git a/include/lldb/Core/ValueObjectSyntheticFilter.h b/include/lldb/Core/ValueObjectSyntheticFilter.h index 49c5601dc0e5..aa784add7409 100644 --- a/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -140,6 +140,9 @@ class ValueObjectSynthetic : public ValueObject return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes); } + virtual bool + SetValueFromCString (const char *value_str, Error& error); + protected: virtual bool UpdateValue (); diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h index 2d4e03ad9b5d..8b90dd0c4895 100644 --- a/include/lldb/DataFormatters/TypeSummary.h +++ b/include/lldb/DataFormatters/TypeSummary.h @@ -23,6 +23,8 @@ #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/ValueObject.h" #include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Symbol/Type.h" @@ -372,31 +374,27 @@ namespace lldb_private { // simple string-based summaries, using ${var to show data struct StringSummaryFormat : public TypeSummaryImpl { - std::string m_format; + std::string m_format_str; + FormatEntity::Entry m_format; + Error m_error; StringSummaryFormat(const TypeSummaryImpl::Flags& flags, const char* f); - const char* - GetSummaryString () const - { - return m_format.c_str(); - } - - void - SetSummaryString (const char* data) - { - if (data) - m_format.assign(data); - else - m_format.clear(); - } - virtual ~StringSummaryFormat() { } + + const char* + GetSummaryString () const + { + return m_format_str.c_str(); + } + void + SetSummaryString (const char* f); + virtual bool FormatObject(ValueObject *valobj, std::string& dest, diff --git a/include/lldb/Expression/ASTResultSynthesizer.h b/include/lldb/Expression/ASTResultSynthesizer.h index 79709de3546a..410a862fc12a 100644 --- a/include/lldb/Expression/ASTResultSynthesizer.h +++ b/include/lldb/Expression/ASTResultSynthesizer.h @@ -91,7 +91,7 @@ class ASTResultSynthesizer : public clang::SemaConsumer //---------------------------------------------------------------------- /// Passthrough stub //---------------------------------------------------------------------- - void HandleVTable(clang::CXXRecordDecl *RD, bool DefinitionRequired); + void HandleVTable(clang::CXXRecordDecl *RD); //---------------------------------------------------------------------- /// Passthrough stub diff --git a/include/lldb/Expression/ASTStructExtractor.h b/include/lldb/Expression/ASTStructExtractor.h index 9e467797a398..25193744c9e0 100644 --- a/include/lldb/Expression/ASTStructExtractor.h +++ b/include/lldb/Expression/ASTStructExtractor.h @@ -99,7 +99,7 @@ class ASTStructExtractor : public clang::SemaConsumer //---------------------------------------------------------------------- /// Passthrough stub //---------------------------------------------------------------------- - void HandleVTable(clang::CXXRecordDecl *RD, bool DefinitionRequired); + void HandleVTable(clang::CXXRecordDecl *RD); //---------------------------------------------------------------------- /// Passthrough stub diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h index c15c65c92a3b..bd1a795a158e 100644 --- a/include/lldb/Expression/IRExecutionUnit.h +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -207,6 +207,9 @@ class IRExecutionUnit : DisassembleFunction (Stream &stream, lldb::ProcessSP &process_sp); + void + ReportSymbolLookupError(const ConstString &name); + class MemoryManager : public llvm::SectionMemoryManager { public: @@ -282,10 +285,10 @@ class IRExecutionUnit : //------------------------------------------------------------------ /// Passthrough interface stub //------------------------------------------------------------------ + virtual uint64_t getSymbolAddress(const std::string &Name); + virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return m_default_mm_ap->getPointerToNamedFunction(Name, AbortOnFailure); - } + bool AbortOnFailure = true); private: std::unique_ptr m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it. IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. @@ -390,6 +393,7 @@ class IRExecutionUnit : std::vector m_cpu_features; llvm::SmallVector m_jitted_functions; ///< A vector of all functions that have been JITted into machine code const ConstString m_name; + std::vector m_failed_lookups; std::atomic m_did_jit; diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h index 2738679b5e03..8219cc06fdc2 100644 --- a/include/lldb/Host/File.h +++ b/include/lldb/Host/File.h @@ -42,7 +42,8 @@ class File : public IOObject eOpenOptionNonBlocking = (1u << 4), // File reads eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist eOpenOptionCanCreateNewOnly = (1u << 6), // Can create file only if it doesn't already exist - eOpenoptionDontFollowSymlinks = (1u << 7) + eOpenoptionDontFollowSymlinks = (1u << 7), + eOpenOptionCloseOnExec = (1u << 8) // Close the file when executing a new process }; static mode_t diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h index ce12689fc047..9a68c698c826 100644 --- a/include/lldb/Host/Host.h +++ b/include/lldb/Host/Host.h @@ -246,9 +246,6 @@ class Host static const lldb_private::UnixSignalsSP& GetUnixSignals (); - static lldb::pid_t - LaunchApplication (const FileSpec &app_file_spec); - static Error LaunchProcess (ProcessLaunchInfo &launch_info); diff --git a/include/lldb/Host/PipeBase.h b/include/lldb/Host/PipeBase.h index 8cad2507d32c..5ef2bb530281 100644 --- a/include/lldb/Host/PipeBase.h +++ b/include/lldb/Host/PipeBase.h @@ -14,6 +14,7 @@ #include #include "lldb/Core/Error.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" namespace lldb_private @@ -25,6 +26,7 @@ class PipeBase virtual Error CreateNew(bool child_process_inherit) = 0; virtual Error CreateNew(llvm::StringRef name, bool child_process_inherit) = 0; + virtual Error CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl& name) = 0; virtual Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) = 0; diff --git a/include/lldb/Host/Socket.h b/include/lldb/Host/Socket.h index 77069ae35f79..ee85f85fcaf2 100644 --- a/include/lldb/Host/Socket.h +++ b/include/lldb/Host/Socket.h @@ -70,22 +70,35 @@ class Socket : public IOObject int GetOption (int level, int option_name, int &option_value); int SetOption (int level, int option_name, int option_value); - static uint16_t GetPortNumber(const NativeSocket& socket); - uint16_t GetPortNumber () const; + // returns port number or 0 if error + static uint16_t GetLocalPortNumber (const NativeSocket& socket); + + // returns port number or 0 if error + uint16_t GetLocalPortNumber () const; + + // returns ip address string or empty string if error + std::string GetLocalIPAddress () const; + + // must be connected + // returns port number or 0 if error + uint16_t GetRemotePortNumber () const; + + // must be connected + // returns ip address string or empty string if error + std::string GetRemoteIPAddress () const; NativeSocket GetNativeSocket () const { return m_socket; } - SocketProtocol GetSocketProtocol() const { return m_protocol; } + SocketProtocol GetSocketProtocol () const { return m_protocol; } virtual Error Read (void *buf, size_t &num_bytes); virtual Error Write (const void *buf, size_t &num_bytes); - virtual Error PreDisconnect(); - virtual Error Close(); + virtual Error PreDisconnect (); + virtual Error Close (); - virtual bool IsValid() const { return m_socket != kInvalidSocketValue; } - virtual WaitableHandle GetWaitableHandle(); + virtual bool IsValid () const { return m_socket != kInvalidSocketValue; } + virtual WaitableHandle GetWaitableHandle (); -protected: static bool DecodeHostAndPort (llvm::StringRef host_and_port, std::string &host_str, @@ -93,7 +106,7 @@ class Socket : public IOObject int32_t& port, Error *error_ptr); - +protected: SocketProtocol m_protocol; NativeSocket m_socket; SocketAddress m_udp_send_sockaddr; // Send address used for UDP connections. diff --git a/include/lldb/Host/SocketAddress.h b/include/lldb/Host/SocketAddress.h index 3598a42a82d0..9666f56489f6 100644 --- a/include/lldb/Host/SocketAddress.h +++ b/include/lldb/Host/SocketAddress.h @@ -31,6 +31,7 @@ typedef ADDRESS_FAMILY sa_family_t; // C++ Includes // Other libraries and framework includes // Project includes +#include namespace lldb_private { @@ -99,6 +100,12 @@ class SocketAddress void SetFamily (sa_family_t family); + //------------------------------------------------------------------ + // Get the address + //------------------------------------------------------------------ + std::string + GetIPAddress () const; + //------------------------------------------------------------------ // Get the port if the socket address for the family has a port //------------------------------------------------------------------ diff --git a/include/lldb/Host/StringConvert.h b/include/lldb/Host/StringConvert.h new file mode 100644 index 000000000000..3cc260cf2be1 --- /dev/null +++ b/include/lldb/Host/StringConvert.h @@ -0,0 +1,45 @@ +//===-- StringConvert.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StringConvert_h_ +#define liblldb_StringConvert_h_ + +// C Includes +#include + +// C++ Includes + +// Other libraries and framework includes +// Project includes + +namespace lldb_private { + +namespace StringConvert { + +//---------------------------------------------------------------------- +/// @namespace StringConvert StringConvert.h "lldb/Host/StringConvert.h" +/// @brief Utility classes for converting strings into Integers +//---------------------------------------------------------------------- + +int32_t +ToSInt32 (const char *s, int32_t fail_value = 0, int base = 0, bool *success_ptr = nullptr); + +uint32_t +ToUInt32 (const char *s, uint32_t fail_value = 0, int base = 0, bool *success_ptr = nullptr); + +int64_t +ToSInt64 (const char *s, int64_t fail_value = 0, int base = 0, bool *success_ptr = nullptr); + +uint64_t +ToUInt64 (const char *s, uint64_t fail_value = 0, int base = 0, bool *success_ptr = nullptr); + +} // namespace StringConvert +} // namespace lldb_private + +#endif diff --git a/source/Host/common/NativeBreakpoint.h b/include/lldb/Host/common/NativeBreakpoint.h similarity index 100% rename from source/Host/common/NativeBreakpoint.h rename to include/lldb/Host/common/NativeBreakpoint.h diff --git a/source/Host/common/NativeBreakpointList.h b/include/lldb/Host/common/NativeBreakpointList.h similarity index 100% rename from source/Host/common/NativeBreakpointList.h rename to include/lldb/Host/common/NativeBreakpointList.h diff --git a/source/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h similarity index 98% rename from source/Host/common/NativeProcessProtocol.h rename to include/lldb/Host/common/NativeProcessProtocol.h index 19d8f353b26f..83c14a5ab37a 100644 --- a/source/Host/common/NativeProcessProtocol.h +++ b/include/lldb/Host/common/NativeProcessProtocol.h @@ -18,6 +18,7 @@ #include "lldb/Host/Mutex.h" #include "NativeBreakpointList.h" +#include "NativeWatchpointList.h" namespace lldb_private { @@ -130,6 +131,9 @@ namespace lldb_private //---------------------------------------------------------------------- // Watchpoint functions //---------------------------------------------------------------------- + virtual const NativeWatchpointList::WatchpointMap& + GetWatchpointMap () const; + virtual uint32_t GetMaxWatchpoints () const; @@ -295,6 +299,7 @@ namespace lldb_private Mutex m_delegates_mutex; std::vector m_delegates; NativeBreakpointList m_breakpoint_list; + NativeWatchpointList m_watchpoint_list; int m_terminal_fd; uint32_t m_stop_id; diff --git a/include/lldb/Target/NativeRegisterContext.h b/include/lldb/Host/common/NativeRegisterContext.h similarity index 97% rename from include/lldb/Target/NativeRegisterContext.h rename to include/lldb/Host/common/NativeRegisterContext.h index fa4ab013f234..e9c03e3c20a4 100644 --- a/include/lldb/Target/NativeRegisterContext.h +++ b/include/lldb/Host/common/NativeRegisterContext.h @@ -15,6 +15,7 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" +#include "lldb/Host/common/NativeWatchpointList.h" namespace lldb_private { @@ -44,6 +45,9 @@ class NativeRegisterContext: virtual uint32_t GetRegisterCount () const = 0; + virtual uint32_t + GetUserRegisterCount () const = 0; + virtual const RegisterInfo * GetRegisterInfoAtIndex (uint32_t reg) const = 0; @@ -92,6 +96,9 @@ class NativeRegisterContext: virtual bool ClearHardwareWatchpoint (uint32_t hw_index); + virtual Error + ClearAllHardwareWatchpoints (); + virtual bool HardwareSingleStep (bool enable); diff --git a/include/lldb/Target/NativeRegisterContextRegisterInfo.h b/include/lldb/Host/common/NativeRegisterContextRegisterInfo.h similarity index 95% rename from include/lldb/Target/NativeRegisterContextRegisterInfo.h rename to include/lldb/Host/common/NativeRegisterContextRegisterInfo.h index 5631005ca56e..b2a29de4e5a4 100644 --- a/include/lldb/Target/NativeRegisterContextRegisterInfo.h +++ b/include/lldb/Host/common/NativeRegisterContextRegisterInfo.h @@ -31,6 +31,9 @@ namespace lldb_private uint32_t GetRegisterCount () const override; + uint32_t + GetUserRegisterCount () const override; + const RegisterInfo * GetRegisterInfoAtIndex (uint32_t reg_index) const override; diff --git a/source/Host/common/NativeThreadProtocol.h b/include/lldb/Host/common/NativeThreadProtocol.h similarity index 93% rename from source/Host/common/NativeThreadProtocol.h rename to include/lldb/Host/common/NativeThreadProtocol.h index 15ecffe8b82d..954ffb36a94f 100644 --- a/source/Host/common/NativeThreadProtocol.h +++ b/include/lldb/Host/common/NativeThreadProtocol.h @@ -53,10 +53,7 @@ namespace lldb_private RestoreAllRegisters (lldb::DataBufferSP &data_sp); virtual bool - GetStopReason (ThreadStopInfo &stop_info) = 0; - - virtual uint32_t - TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const; + GetStopReason (ThreadStopInfo &stop_info, std::string& description) = 0; lldb::tid_t GetID() const diff --git a/include/lldb/Host/common/NativeWatchpointList.h b/include/lldb/Host/common/NativeWatchpointList.h new file mode 100644 index 000000000000..7b310e5a0db0 --- /dev/null +++ b/include/lldb/Host/common/NativeWatchpointList.h @@ -0,0 +1,47 @@ +//===-- NativeWatchpointList.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NativeWatchpointList_h_ +#define liblldb_NativeWatchpointList_h_ + +#include "lldb/lldb-private-forward.h" +#include "lldb/Core/Error.h" + +#include + +namespace lldb_private +{ + struct NativeWatchpoint + { + lldb::addr_t m_addr; + size_t m_size; + uint32_t m_watch_flags; + bool m_hardware; + }; + + class NativeWatchpointList + { + public: + Error + Add (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware); + + Error + Remove (lldb::addr_t addr); + + using WatchpointMap = std::map; + + const WatchpointMap& + GetWatchpointMap () const; + + private: + WatchpointMap m_watchpoints; + }; +} + +#endif // ifndef liblldb_NativeWatchpointList_h_ diff --git a/source/Host/common/SoftwareBreakpoint.h b/include/lldb/Host/common/SoftwareBreakpoint.h similarity index 100% rename from source/Host/common/SoftwareBreakpoint.h rename to include/lldb/Host/common/SoftwareBreakpoint.h diff --git a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h index 4d326d71fa75..660b9d169bfc 100644 --- a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -50,6 +50,8 @@ class ConnectionFileDescriptor : public Connection virtual size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + virtual std::string GetURI(); + lldb::ConnectionStatus BytesAvailable(uint32_t timeout_usec, Error *error_ptr); bool InterruptRead(); @@ -75,7 +77,7 @@ class ConnectionFileDescriptor : public Connection void CloseCommandPipe(); - lldb::ConnectionStatus SocketListen(const char *host_and_port, Error *error_ptr); + lldb::ConnectionStatus SocketListenAndAccept(const char *host_and_port, Error *error_ptr); lldb::ConnectionStatus ConnectTCP(const char *host_and_port, Error *error_ptr); @@ -99,6 +101,8 @@ class ConnectionFileDescriptor : public Connection bool m_waiting_for_accept; bool m_child_processes_inherit; + std::string m_uri; + private: DISALLOW_COPY_AND_ASSIGN(ConnectionFileDescriptor); }; diff --git a/include/lldb/Host/posix/PipePosix.h b/include/lldb/Host/posix/PipePosix.h index 0ab3ff7f6775..fbdac66149d6 100644 --- a/include/lldb/Host/posix/PipePosix.h +++ b/include/lldb/Host/posix/PipePosix.h @@ -36,6 +36,8 @@ class PipePosix : public PipeBase Error CreateNew(llvm::StringRef name, bool child_process_inherit) override; Error + CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl& name) override; + Error OpenAsReader(llvm::StringRef name, bool child_process_inherit) override; Error OpenAsWriterWithTimeout(llvm::StringRef name, bool child_process_inherit, const std::chrono::microseconds &timeout) override; diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h index 1071bd6fd047..fe29df468de7 100644 --- a/include/lldb/Interpreter/Args.h +++ b/include/lldb/Interpreter/Args.h @@ -347,18 +347,6 @@ class Args bool trailing = true, bool return_null_if_empty = true); - static int32_t - StringToSInt32 (const char *s, int32_t fail_value = 0, int base = 0, bool *success_ptr = NULL); - - static uint32_t - StringToUInt32 (const char *s, uint32_t fail_value = 0, int base = 0, bool *success_ptr = NULL); - - static int64_t - StringToSInt64 (const char *s, int64_t fail_value = 0, int base = 0, bool *success_ptr = NULL); - - static uint64_t - StringToUInt64 (const char *s, uint64_t fail_value = 0, int base = 0, bool *success_ptr = NULL); - static bool UInt64ValueIsValidForByteSize (uint64_t uval64, size_t total_byte_size) { diff --git a/include/lldb/Interpreter/CommandInterpreter.h b/include/lldb/Interpreter/CommandInterpreter.h index baaa271a4285..20b6ff95be8b 100644 --- a/include/lldb/Interpreter/CommandInterpreter.h +++ b/include/lldb/Interpreter/CommandInterpreter.h @@ -224,6 +224,7 @@ class CommandInterpreter : 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 }; @@ -430,6 +431,11 @@ class CommandInterpreter : const char *command_name, StreamString &help_string); + void + OutputFormattedHelpText (Stream &strm, + const char *prefix, + const char *help_text); + void OutputFormattedHelpText (Stream &stream, const char *command_word, @@ -607,6 +613,9 @@ class CommandInterpreter : bool asynchronously, void *baton); + const char * + GetCommandPrefix (); + //------------------------------------------------------------------ // Properties //------------------------------------------------------------------ diff --git a/include/lldb/Interpreter/OptionGroupPlatform.h b/include/lldb/Interpreter/OptionGroupPlatform.h index 970ad328ccb7..f7de50c86a56 100644 --- a/include/lldb/Interpreter/OptionGroupPlatform.h +++ b/include/lldb/Interpreter/OptionGroupPlatform.h @@ -102,8 +102,10 @@ class OptionGroupPlatform : public OptionGroup SetSDKBuild (const ConstString &sdk_build) { m_sdk_build = sdk_build; - } - + } + + bool + PlatformMatches(const lldb::PlatformSP &platform_sp) const; protected: std::string m_platform_name; diff --git a/include/lldb/Interpreter/OptionValue.h b/include/lldb/Interpreter/OptionValue.h index 0e8f23453a8a..787430a96ef5 100644 --- a/include/lldb/Interpreter/OptionValue.h +++ b/include/lldb/Interpreter/OptionValue.h @@ -17,6 +17,7 @@ #include "lldb/lldb-defines.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" +#include "lldb/Core/FormatEntity.h" namespace lldb_private { @@ -45,7 +46,8 @@ namespace lldb_private { eTypeSInt64, eTypeString, eTypeUInt64, - eTypeUUID + eTypeUUID, + eTypeFormatEntity } Type; enum { @@ -309,7 +311,13 @@ namespace lldb_private { const OptionValueUUID * GetAsUUID () const; - + + OptionValueFormatEntity * + GetAsFormatEntity (); + + const OptionValueFormatEntity * + GetAsFormatEntity () const; + bool GetBooleanValue (bool fail_value = false) const; @@ -341,6 +349,9 @@ namespace lldb_private { bool SetFormatValue (lldb::Format new_value); + const FormatEntity::Entry * + GetFormatEntity () const; + const RegularExpression * GetRegexValue () const; diff --git a/include/lldb/Interpreter/OptionValueFormatEntity.h b/include/lldb/Interpreter/OptionValueFormatEntity.h new file mode 100644 index 000000000000..cc988998bda0 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -0,0 +1,107 @@ +//===-- OptionValueFormatEntity.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_OptionValueFormatEntity_h_ +#define liblldb_OptionValueFormatEntity_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/FormatEntity.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueFormatEntity : public OptionValue +{ +public: + OptionValueFormatEntity (const char *default_format); + + virtual + ~OptionValueFormatEntity() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + OptionValue::Type + GetType () const override + { + return eTypeFormatEntity; + } + + void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + + Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign) override; + + bool + Clear () override; + + lldb::OptionValueSP + DeepCopy () const override; + + size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + FormatEntity::Entry & + GetCurrentValue() + { + return m_current_entry; + } + + const FormatEntity::Entry & + GetCurrentValue() const + { + return m_current_entry; + } + + void + SetCurrentValue (const FormatEntity::Entry &value) + { + m_current_entry = value; + } + + FormatEntity::Entry & + GetDefaultValue() + { + return m_default_entry; + } + + const FormatEntity::Entry & + GetDefaultValue() const + { + return m_default_entry; + } + + +protected: + std::string m_current_format; + std::string m_default_format; + FormatEntity::Entry m_current_entry; + FormatEntity::Entry m_default_entry; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueFormatEntity_h_ diff --git a/include/lldb/Interpreter/OptionValueProperties.h b/include/lldb/Interpreter/OptionValueProperties.h index a67ea5d66e54..6f7f4995ed15 100644 --- a/include/lldb/Interpreter/OptionValueProperties.h +++ b/include/lldb/Interpreter/OptionValueProperties.h @@ -15,6 +15,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/ConstString.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Interpreter/OptionValue.h" #include "lldb/Interpreter/Property.h" @@ -191,6 +192,9 @@ class OptionValueProperties : bool SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value); + const FormatEntity::Entry * + GetPropertyAtIndexAsFormatEntity (const ExecutionContext *exe_ctx, uint32_t idx); + const RegularExpression * GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const; diff --git a/include/lldb/Interpreter/OptionValueRegex.h b/include/lldb/Interpreter/OptionValueRegex.h index bb8c4588e22a..295bb98b69e6 100644 --- a/include/lldb/Interpreter/OptionValueRegex.h +++ b/include/lldb/Interpreter/OptionValueRegex.h @@ -24,9 +24,9 @@ namespace lldb_private { class OptionValueRegex : public OptionValue { public: - OptionValueRegex (const char *value = NULL, uint32_t regex_flags = 0) : + OptionValueRegex (const char *value = NULL) : OptionValue(), - m_regex (value, regex_flags) + m_regex (value) { } @@ -75,10 +75,10 @@ class OptionValueRegex : public OptionValue } void - SetCurrentValue (const char *value, uint32_t regex_flags) + SetCurrentValue (const char *value) { if (value && value[0]) - m_regex.Compile (value, regex_flags); + m_regex.Compile (value); else m_regex.Clear(); } diff --git a/include/lldb/Interpreter/OptionValues.h b/include/lldb/Interpreter/OptionValues.h index c66fc4dab2f6..2ccab994674b 100644 --- a/include/lldb/Interpreter/OptionValues.h +++ b/include/lldb/Interpreter/OptionValues.h @@ -21,6 +21,7 @@ #include "lldb/Interpreter/OptionValueFileSpec.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueFormat.h" +#include "lldb/Interpreter/OptionValueFormatEntity.h" #include "lldb/Interpreter/OptionValuePathMappings.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/OptionValueRegex.h" diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h index 35ba9491ded0..1b4b88161927 100644 --- a/include/lldb/Interpreter/ScriptInterpreter.h +++ b/include/lldb/Interpreter/ScriptInterpreter.h @@ -240,7 +240,13 @@ class ScriptInterpreter bool m_set_lldb_globals; bool m_maskout_errors; }; - + + virtual bool + Interrupt() + { + return false; + } + virtual bool ExecuteOneLine (const char *command, CommandReturnObject *result, @@ -290,13 +296,13 @@ class ScriptInterpreter } virtual bool - GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token = NULL) + GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token = NULL) { return false; } virtual bool - GenerateTypeScriptFunction (StringList &input, std::string& output, void* name_token = NULL) + GenerateTypeScriptFunction (StringList &input, std::string& output, const void* name_token = NULL) { return false; } @@ -308,13 +314,13 @@ class ScriptInterpreter } virtual bool - GenerateTypeSynthClass (StringList &input, std::string& output, void* name_token = NULL) + GenerateTypeSynthClass (StringList &input, std::string& output, const void* name_token = NULL) { return false; } virtual bool - GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token = NULL) + GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token = NULL) { return false; } diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h index edcc4c44facb..94ed16e02ca2 100644 --- a/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -40,126 +40,129 @@ class ScriptInterpreterPython : ~ScriptInterpreterPython (); + bool + Interrupt() override; + bool ExecuteOneLine (const char *command, CommandReturnObject *result, - const ExecuteScriptOptions &options = ExecuteScriptOptions()); + const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; void - ExecuteInterpreterLoop (); + ExecuteInterpreterLoop () override; bool ExecuteOneLineWithReturn (const char *in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, - const ExecuteScriptOptions &options = ExecuteScriptOptions()); + const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; lldb_private::Error ExecuteMultipleLines (const char *in_string, - const ExecuteScriptOptions &options = ExecuteScriptOptions()); + const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; Error - ExportFunctionDefinitionToInterpreter (StringList &function_def); + ExportFunctionDefinitionToInterpreter (StringList &function_def) override; bool - GenerateTypeScriptFunction (StringList &input, std::string& output, void* name_token = NULL); + GenerateTypeScriptFunction (StringList &input, std::string& output, const void* name_token = NULL) override; bool - GenerateTypeSynthClass (StringList &input, std::string& output, void* name_token = NULL); + GenerateTypeSynthClass (StringList &input, std::string& output, const void* name_token = NULL) override; bool - GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token = NULL); + GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token = NULL) override; // use this if the function code is just a one-liner script bool - GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token = NULL); + GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token = NULL) override; - virtual bool - GenerateScriptAliasFunction (StringList &input, std::string& output); + bool + GenerateScriptAliasFunction (StringList &input, std::string& output) override; lldb::ScriptInterpreterObjectSP CreateSyntheticScriptedProvider (const char *class_name, - lldb::ValueObjectSP valobj); + lldb::ValueObjectSP valobj) override; lldb::ScriptInterpreterObjectSP - virtual CreateScriptedThreadPlan (const char *class_name, - lldb::ThreadPlanSP thread_plan); + CreateScriptedThreadPlan (const char *class_name, + lldb::ThreadPlanSP thread_plan) override; - virtual bool + bool ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, Event *event, - bool &script_error); - virtual bool + bool &script_error) override; + bool ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, Event *event, - bool &script_error); - virtual lldb::StateType + bool &script_error) override; + lldb::StateType ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, - bool &script_error); + bool &script_error) override; - virtual lldb::ScriptInterpreterObjectSP + lldb::ScriptInterpreterObjectSP OSPlugin_CreatePluginObject (const char *class_name, - lldb::ProcessSP process_sp); + lldb::ProcessSP process_sp) override; - virtual lldb::ScriptInterpreterObjectSP - OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp); + lldb::ScriptInterpreterObjectSP + OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) override; - virtual lldb::ScriptInterpreterObjectSP - OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp); + lldb::ScriptInterpreterObjectSP + OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) override; - virtual lldb::ScriptInterpreterObjectSP + lldb::ScriptInterpreterObjectSP OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t thread_id); + lldb::tid_t thread_id) override; - virtual lldb::ScriptInterpreterObjectSP + lldb::ScriptInterpreterObjectSP OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, lldb::tid_t tid, - lldb::addr_t context); + lldb::addr_t context) override; - virtual lldb::ScriptInterpreterObjectSP + lldb::ScriptInterpreterObjectSP LoadPluginModule (const FileSpec& file_spec, - lldb_private::Error& error); + lldb_private::Error& error) override; - virtual lldb::ScriptInterpreterObjectSP + lldb::ScriptInterpreterObjectSP GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp, Target* target, const char* setting_name, - lldb_private::Error& error); + lldb_private::Error& error) override; - virtual size_t - CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor); + size_t + CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor) override; - virtual lldb::ValueObjectSP - GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor, uint32_t idx); + lldb::ValueObjectSP + GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor, uint32_t idx) override; - virtual int - GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name); + int + GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name) override; - virtual bool - UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor); + bool + UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) override; - virtual bool - MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor); + bool + MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) override; - virtual lldb::ValueObjectSP - GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor); + lldb::ValueObjectSP + GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor) override; - virtual bool + bool RunScriptBasedCommand(const char* impl_function, const char* args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject& cmd_retobj, Error& error, - const lldb_private::ExecutionContext& exe_ctx); + const lldb_private::ExecutionContext& exe_ctx) override; Error - GenerateFunction(const char *signature, const StringList &input); + GenerateFunction(const char *signature, const StringList &input) override; Error - GenerateBreakpointCommandCallbackData (StringList &input, std::string& output); + GenerateBreakpointCommandCallbackData (StringList &input, std::string& output) override; bool - GenerateWatchpointCommandCallbackData (StringList &input, std::string& output); + GenerateWatchpointCommandCallbackData (StringList &input, std::string& output) override; // static size_t // GenerateBreakpointOptionsCommandCallback (void *baton, @@ -186,21 +189,21 @@ class ScriptInterpreterPython : StoppointCallbackContext *context, lldb::user_id_t watch_id); - virtual bool + bool GetScriptedSummary (const char *function_name, lldb::ValueObjectSP valobj, lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, const TypeSummaryOptions& options, - std::string& retval); + std::string& retval) override; - virtual void - Clear (); + void + Clear () override; - virtual bool - GetDocumentationForItem (const char* item, std::string& dest); + bool + GetDocumentationForItem (const char* item, std::string& dest) override; - virtual bool - CheckObjectExists (const char* name) + bool + CheckObjectExists (const char* name) override { if (!name || !name[0]) return false; @@ -208,76 +211,76 @@ class ScriptInterpreterPython : return GetDocumentationForItem (name,temp); } - virtual bool + bool RunScriptFormatKeyword (const char* impl_function, Process* process, std::string& output, - Error& error); + Error& error) override; - virtual bool + bool RunScriptFormatKeyword (const char* impl_function, Thread* thread, std::string& output, - Error& error); + Error& error) override; - virtual bool + bool RunScriptFormatKeyword (const char* impl_function, Target* target, std::string& output, - Error& error); + Error& error) override; - virtual bool + bool RunScriptFormatKeyword (const char* impl_function, StackFrame* frame, std::string& output, - Error& error); + Error& error) override; - virtual bool + bool RunScriptFormatKeyword (const char* impl_function, ValueObject* value, std::string& output, - Error& error); + Error& error) override; - virtual bool + bool LoadScriptingModule (const char* filename, bool can_reload, bool init_session, lldb_private::Error& error, - lldb::ScriptInterpreterObjectSP* module_sp = nullptr); + lldb::ScriptInterpreterObjectSP* module_sp = nullptr) override; - virtual lldb::ScriptInterpreterObjectSP - MakeScriptObject (void* object); + lldb::ScriptInterpreterObjectSP + MakeScriptObject (void* object) override; - virtual std::unique_ptr - AcquireInterpreterLock (); + std::unique_ptr + AcquireInterpreterLock () override; void CollectDataForBreakpointCommandCallback (std::vector &bp_options_vec, - CommandReturnObject &result); + CommandReturnObject &result) override; void CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, - CommandReturnObject &result); + CommandReturnObject &result) override; /// Set the callback body text into the callback for the breakpoint. Error SetBreakpointCommandCallback (BreakpointOptions *bp_options, - const char *callback_body); + const char *callback_body) override; void SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, - const char *function_name); + const char *function_name) override; /// Set a one-liner as the callback for the watchpoint. void SetWatchpointCommandCallback (WatchpointOptions *wp_options, - const char *oneliner); + const char *oneliner) override; StringList ReadCommandInputFromUser (FILE *in_file); virtual void - ResetOutputFileHandle (FILE *new_fh); + ResetOutputFileHandle (FILE *new_fh) override; static void InitializePrivate (); @@ -331,11 +334,11 @@ class ScriptInterpreterPython : //---------------------------------------------------------------------- // IOHandlerDelegate //---------------------------------------------------------------------- - virtual void - IOHandlerActivated (IOHandler &io_handler); + void + IOHandlerActivated (IOHandler &io_handler) override; - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data); + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override; protected: @@ -448,6 +451,26 @@ class ScriptInterpreterPython : }; protected: + uint32_t + IsExecutingPython () const + { + return m_lock_count > 0; + } + + uint32_t + IncrementLockCount() + { + return ++m_lock_count; + } + + uint32_t + DecrementLockCount() + { + if (m_lock_count > 0) + --m_lock_count; + return m_lock_count; + } + enum ActiveIOHandler { eIOHandlerNone, eIOHandlerBreakpoint, @@ -480,6 +503,7 @@ class ScriptInterpreterPython : bool m_session_is_active; bool m_pty_slave_is_open; bool m_valid_session; + uint32_t m_lock_count; PyThreadState *m_command_thread_state; }; } // namespace lldb_private diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h index ef23a8be645b..94c768780a00 100644 --- a/include/lldb/Symbol/ClangASTType.h +++ b/include/lldb/Symbol/ClangASTType.h @@ -96,6 +96,10 @@ class ClangASTType uint64_t *size, bool *is_incomplete) const; + bool + IsVectorType (ClangASTType *element_type, + uint64_t *size) const; + bool IsArrayOfScalarType () const; @@ -347,10 +351,10 @@ class ClangASTType //---------------------------------------------------------------------- uint64_t - GetByteSize () const; + GetByteSize (ExecutionContext *exe_ctx) const; uint64_t - GetBitSize () const; + GetBitSize (ExecutionContext *exe_ctx) const; lldb::Encoding GetEncoding (uint64_t &count) const; diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h index bdc6ae8c9e81..8bcf92de42e5 100644 --- a/include/lldb/Symbol/ObjectFile.h +++ b/include/lldb/Symbol/ObjectFile.h @@ -767,6 +767,23 @@ friend class lldb_private::Module; return 0; } + + //------------------------------------------------------------------ + /// Return true if this file is a dynamic link editor (dyld) + /// + /// Often times dyld has symbols that mirror symbols in libc and + /// other shared libraries (like "malloc" and "free") and the user + /// does _not_ want to stop in these shared libraries by default. + /// We can ask the ObjectFile if it is such a file and should be + /// avoided for things like settings breakpoints and doing function + /// lookups for expressions. + //------------------------------------------------------------------ + virtual bool + GetIsDynamicLinkEditor() + { + return false; + } + //------------------------------------------------------------------ // Member Functions //------------------------------------------------------------------ diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h index d40d1453cb17..64490627b84d 100644 --- a/include/lldb/Symbol/SymbolContext.h +++ b/include/lldb/Symbol/SymbolContext.h @@ -347,6 +347,7 @@ class SymbolContext Block * block; ///< The Block for a given query LineEntry line_entry; ///< The LineEntry for a given query Symbol * symbol; ///< The Symbol for a given query + Variable * variable; ///< The global variable matching the given query }; diff --git a/include/lldb/Target/FileAction.h b/include/lldb/Target/FileAction.h index 228a9e6098c1..4015cbb5ea89 100644 --- a/include/lldb/Target/FileAction.h +++ b/include/lldb/Target/FileAction.h @@ -1,4 +1,4 @@ -//===-- ProcessLaunchInfo.h -------------------------------------*- C++ -*-===// +//===-- FileAction.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h index 0aaa67c2382c..d5ed81956475 100644 --- a/include/lldb/Target/LanguageRuntime.h +++ b/include/lldb/Target/LanguageRuntime.h @@ -102,6 +102,13 @@ class LanguageRuntime : virtual lldb::SearchFilterSP CreateExceptionSearchFilter (); + + virtual bool + GetTypeBitSize (const ClangASTType& clang_type, + uint64_t &size) + { + return false; + } protected: //------------------------------------------------------------------ diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h index a3fee91428fa..42a391478e3e 100644 --- a/include/lldb/Target/ObjCLanguageRuntime.h +++ b/include/lldb/Target/ObjCLanguageRuntime.h @@ -20,6 +20,7 @@ // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/Type.h" @@ -514,6 +515,10 @@ class ObjCLanguageRuntime : m_negative_complete_class_cache.clear(); } + virtual bool + GetTypeBitSize (const ClangASTType& clang_type, + uint64_t &size); + protected: //------------------------------------------------------------------ // Classes that inherit from ObjCLanguageRuntime can see and modify these @@ -610,11 +615,13 @@ class ObjCLanguageRuntime : typedef std::multimap HashToISAMap; typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; typedef HashToISAMap::iterator HashToISAIterator; + typedef ThreadSafeDenseMap TypeSizeCache; MsgImplMap m_impl_cache; LazyBool m_has_new_literals_and_indexing; ISAToDescriptorMap m_isa_to_descriptor; HashToISAMap m_hash_to_isa_map; + TypeSizeCache m_type_size_cache; protected: uint32_t m_isa_to_descriptor_stop_id; diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h index 8b14cc2a0ece..f4596bd00f0b 100644 --- a/include/lldb/Target/Platform.h +++ b/include/lldb/Target/Platform.h @@ -28,7 +28,7 @@ // TODO pull NativeDelegate class out of NativeProcessProtocol so we // can just forward ref the NativeDelegate rather than include it here. -#include "../../../source/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" namespace lldb_private { @@ -379,6 +379,12 @@ namespace lldb_private { virtual Error LaunchProcess (ProcessLaunchInfo &launch_info); + //------------------------------------------------------------------ + /// Kill process on a platform. + //------------------------------------------------------------------ + virtual Error + KillProcess (const lldb::pid_t pid); + //------------------------------------------------------------------ /// Lets a platform answer if it is compatible with a given /// architecture and the target triple contained within. @@ -569,7 +575,7 @@ namespace lldb_private { // Appends the platform-specific options required to find the modules for the current platform. virtual void - AddClangModuleCompilationOptions (std::vector &options); + AddClangModuleCompilationOptions (Target *target, std::vector &options); ConstString GetWorkingDirectory (); @@ -952,8 +958,7 @@ namespace lldb_private { uint32_t m_update_os_version; ArchSpec m_system_arch; // The architecture of the kernel or the remote platform typedef std::map IDToNameMap; - Mutex m_uid_map_mutex; - Mutex m_gid_map_mutex; + Mutex m_mutex; // Mutex for modifying Platform data structures that should only be used for non-reentrant code IDToNameMap m_uid_map; IDToNameMap m_gid_map; size_t m_max_uid_name_len; @@ -967,7 +972,6 @@ namespace lldb_private { std::string m_local_cache_directory; std::vector m_trap_handlers; bool m_calculated_trap_handlers; - Mutex m_trap_handler_mutex; //------------------------------------------------------------------ /// Ask the Platform subclass to fill in the list of trap handler names @@ -988,7 +992,7 @@ namespace lldb_private { const char * GetCachedUserName (uint32_t uid) { - Mutex::Locker locker (m_uid_map_mutex); + Mutex::Locker locker (m_mutex); IDToNameMap::iterator pos = m_uid_map.find (uid); if (pos != m_uid_map.end()) { @@ -1004,7 +1008,7 @@ namespace lldb_private { const char * SetCachedUserName (uint32_t uid, const char *name, size_t name_len) { - Mutex::Locker locker (m_uid_map_mutex); + Mutex::Locker locker (m_mutex); ConstString const_name (name); m_uid_map[uid] = const_name; if (m_max_uid_name_len < name_len) @@ -1016,7 +1020,7 @@ namespace lldb_private { void SetUserNameNotFound (uint32_t uid) { - Mutex::Locker locker (m_uid_map_mutex); + Mutex::Locker locker (m_mutex); m_uid_map[uid] = ConstString(); } @@ -1024,14 +1028,14 @@ namespace lldb_private { void ClearCachedUserNames () { - Mutex::Locker locker (m_uid_map_mutex); + Mutex::Locker locker (m_mutex); m_uid_map.clear(); } const char * GetCachedGroupName (uint32_t gid) { - Mutex::Locker locker (m_gid_map_mutex); + Mutex::Locker locker (m_mutex); IDToNameMap::iterator pos = m_gid_map.find (gid); if (pos != m_gid_map.end()) { @@ -1047,7 +1051,7 @@ namespace lldb_private { const char * SetCachedGroupName (uint32_t gid, const char *name, size_t name_len) { - Mutex::Locker locker (m_gid_map_mutex); + Mutex::Locker locker (m_mutex); ConstString const_name (name); m_gid_map[gid] = const_name; if (m_max_gid_name_len < name_len) @@ -1059,14 +1063,14 @@ namespace lldb_private { void SetGroupNameNotFound (uint32_t gid) { - Mutex::Locker locker (m_gid_map_mutex); + Mutex::Locker locker (m_mutex); m_gid_map[gid] = ConstString(); } void ClearCachedGroupNames () { - Mutex::Locker locker (m_gid_map_mutex); + Mutex::Locker locker (m_mutex); m_gid_map.clear(); } diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index e04de511c797..6608391b94fd 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -678,13 +678,16 @@ friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs); bool IsLastResumeForUserExpression () const { + // If we haven't yet resumed the target, then it can't be for a user expression... + if (m_resume_id == 0) + return false; + return m_resume_id == m_last_user_expression_resume; } void SetRunningUserExpression (bool on) { - // REMOVEME printf ("Setting running user expression %s at resume id %d - value: %d.\n", on ? "on" : "off", m_resume_id, m_running_user_expression); if (on) m_running_user_expression++; else @@ -3177,6 +3180,7 @@ class Process : lldb::IOHandlerSP m_process_input_reader; Communication m_stdio_communication; Mutex m_stdio_communication_mutex; + bool m_stdio_disable; /// Remember process launch setting std::string m_stdout_data; std::string m_stderr_data; Mutex m_profile_data_comm_mutex; diff --git a/include/lldb/Utility/AnsiTerminal.h b/include/lldb/Utility/AnsiTerminal.h index 036950c1bd45..9a5117ae74ea 100644 --- a/include/lldb/Utility/AnsiTerminal.h +++ b/include/lldb/Utility/AnsiTerminal.h @@ -50,37 +50,6 @@ namespace lldb_utility { namespace ansi { - const char *k_escape_start = "\033["; - const char *k_escape_end = "m"; - - const char *k_fg_black = "30"; - const char *k_fg_red = "31"; - const char *k_fg_green = "32"; - const char *k_fg_yellow = "33"; - const char *k_fg_blue = "34"; - const char *k_fg_purple = "35"; - const char *k_fg_cyan = "36"; - const char *k_fg_white = "37"; - - const char *k_bg_black = "40"; - const char *k_bg_red = "41"; - const char *k_bg_green = "42"; - const char *k_bg_yellow = "43"; - const char *k_bg_blue = "44"; - const char *k_bg_purple = "45"; - const char *k_bg_cyan = "46"; - const char *k_bg_white = "47"; - - const char *k_ctrl_normal = "0"; - const char *k_ctrl_bold = "1"; - const char *k_ctrl_faint = "2"; - const char *k_ctrl_italic = "3"; - const char *k_ctrl_underline = "4"; - const char *k_ctrl_slow_blink = "5"; - const char *k_ctrl_fast_blink = "6"; - const char *k_ctrl_negative = "7"; - const char *k_ctrl_conceal = "8"; - const char *k_ctrl_crossed_out = "9"; inline std::string FormatAnsiTerminalCodes(const char *format, bool do_color = true) diff --git a/include/lldb/Utility/ProcessStructReader.h b/include/lldb/Utility/ProcessStructReader.h index 7b05d93151aa..d053b702462e 100644 --- a/include/lldb/Utility/ProcessStructReader.h +++ b/include/lldb/Utility/ProcessStructReader.h @@ -59,7 +59,7 @@ namespace lldb_private { // no support for bitfields in here (yet) if (is_bitfield) return; - auto size = field_type.GetByteSize(); + auto size = field_type.GetByteSize(nullptr); // no support for things larger than a uint64_t (yet) if (size > 8) return; @@ -67,7 +67,7 @@ namespace lldb_private { size_t byte_index = static_cast(bit_offset / 8); m_fields[const_name] = FieldImpl{field_type, byte_index, static_cast(size)}; } - size_t total_size = struct_type.GetByteSize(); + size_t total_size = struct_type.GetByteSize(nullptr); lldb::DataBufferSP buffer_sp(new DataBufferHeap(total_size,0)); Error error; process->ReadMemoryFromInferior(base_addr, diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index 87ee14875734..f70ee0cd7b28 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -290,7 +290,11 @@ namespace lldb { eSymbolContextBlock = (1u << 4), ///< Set when the deepest \a block is requested from a query, or was located in query results eSymbolContextLineEntry = (1u << 5), ///< Set when \a line_entry is requested from a query, or was located in query results eSymbolContextSymbol = (1u << 6), ///< Set when \a symbol is requested from a query, or was located in query results - eSymbolContextEverything = ((eSymbolContextSymbol << 1) - 1u) ///< Indicates to try and lookup everything up during a query. + eSymbolContextEverything = ((eSymbolContextSymbol << 1) - 1u), ///< Indicates to try and lookup everything up during a routine symbol context query. + eSymbolContextVariable = (1u << 7) ///< Set when \a global or static variable is requested from a query, or was located in query results. + ///< eSymbolContextVariable is potentially expensive to lookup so it isn't included in + ///< eSymbolContextEverything which stops it from being used during frame PC lookups and + ///< many other potential address to symbol context lookups. } SymbolContextItem; typedef enum Permissions @@ -374,6 +378,8 @@ namespace lldb { eLanguageTypeUPC = 0x0012, ///< Unified Parallel C. eLanguageTypeD = 0x0013, ///< D. eLanguageTypePython = 0x0014, ///< Python. + // NOTE: The below are DWARF5 constants, subject to change upon + // completion of the DWARF5 specification eLanguageTypeOpenCL = 0x0015, ///< OpenCL. eLanguageTypeGo = 0x0016, ///< Go. eLanguageTypeModula3 = 0x0017, ///< Modula 3. @@ -386,6 +392,9 @@ namespace lldb { eLanguageTypeSwift = 0x001e, ///< Swift. eLanguageTypeJulia = 0x001f, ///< Julia. eLanguageTypeDylan = 0x0020, ///< Dylan. + eLanguageTypeC_plus_plus_14 = 0x0021, ///< ISO C++:2014. + eLanguageTypeFortran03 = 0x0022, ///< ISO Fortran 2003. + eLanguageTypeFortran08 = 0x0023, ///< ISO Fortran 2008. eNumLanguageTypes } LanguageType; diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h index 1ecb2f179bb2..53f59dd62096 100644 --- a/include/lldb/lldb-forward.h +++ b/include/lldb/lldb-forward.h @@ -146,6 +146,7 @@ class OptionValueEnumeration; class OptionValueFileSpec; class OptionValueFileSpecList; class OptionValueFormat; +class OptionValueFormatEntity; class OptionValuePathMappings; class OptionValueProperties; class OptionValueRegex; diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp index eccc4e29aadf..6158418d2f2a 100644 --- a/source/API/SBInstruction.cpp +++ b/source/API/SBInstruction.cpp @@ -178,8 +178,9 @@ SBInstruction::GetDescription (lldb::SBStream &s) module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); // Use the "ref()" instead of the "get()" accessor in case the SBStream // didn't have a stream already created, one will get created... - const char *disassemble_format = "${addr-file-or-load}: "; - m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, disassemble_format); + FormatEntity::Entry format; + FormatEntity::Parse("${addr}: ", format); + m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format); return true; } return false; @@ -199,8 +200,9 @@ SBInstruction::Print (FILE *out) if (module_sp) module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); StreamFile out_stream (out, false); - const char *disassemble_format = "${addr-file-or-load}: "; - m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, disassemble_format); + FormatEntity::Entry format; + FormatEntity::Parse("${addr}: ", format); + m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format); } } diff --git a/source/API/SBInstructionList.cpp b/source/API/SBInstructionList.cpp index 31585b3e6868..812824b4d2e5 100644 --- a/source/API/SBInstructionList.cpp +++ b/source/API/SBInstructionList.cpp @@ -102,7 +102,8 @@ SBInstructionList::GetDescription (lldb::SBStream &description) // exist already inside description... Stream &sref = description.ref(); const uint32_t max_opcode_byte_size = m_opaque_sp->GetInstructionList().GetMaxOpcocdeByteSize(); - const char *disassemble_format = "${addr-file-or-load}: "; + FormatEntity::Entry format; + FormatEntity::Parse("${addr}: ", format); SymbolContext sc; SymbolContext prev_sc; for (size_t i=0; iResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); } - inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, disassemble_format); + inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, &format); sref.EOL(); } return true; diff --git a/source/API/SBLaunchInfo.cpp b/source/API/SBLaunchInfo.cpp new file mode 100644 index 000000000000..dcb0e1b488ba --- /dev/null +++ b/source/API/SBLaunchInfo.cpp @@ -0,0 +1,278 @@ +//===-- SBLaunchInfo.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "lldb/API/SBLaunchInfo.h" + +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBListener.h" +#include "lldb/Target/ProcessLaunchInfo.h" + +using namespace lldb; +using namespace lldb_private; + +SBLaunchInfo::SBLaunchInfo (const char **argv) : + m_opaque_sp(new ProcessLaunchInfo()) +{ + m_opaque_sp->GetFlags().Reset (eLaunchFlagDebug | eLaunchFlagDisableASLR); + if (argv && argv[0]) + m_opaque_sp->GetArguments().SetArguments(argv); +} + +SBLaunchInfo::~SBLaunchInfo() +{ +} + +lldb_private::ProcessLaunchInfo & +SBLaunchInfo::ref () +{ + return *m_opaque_sp; +} + +lldb::pid_t +SBLaunchInfo::GetProcessID() +{ + return m_opaque_sp->GetProcessID(); +} + +uint32_t +SBLaunchInfo::GetUserID() +{ + return m_opaque_sp->GetUserID(); +} + +uint32_t +SBLaunchInfo::GetGroupID() +{ + return m_opaque_sp->GetGroupID(); +} + +bool +SBLaunchInfo::UserIDIsValid () +{ + return m_opaque_sp->UserIDIsValid(); +} + +bool +SBLaunchInfo::GroupIDIsValid () +{ + return m_opaque_sp->GroupIDIsValid(); +} + +void +SBLaunchInfo::SetUserID (uint32_t uid) +{ + m_opaque_sp->SetUserID (uid); +} + +void +SBLaunchInfo::SetGroupID (uint32_t gid) +{ + m_opaque_sp->SetGroupID (gid); +} + +SBFileSpec +SBLaunchInfo::GetExecutableFile () +{ + return SBFileSpec (m_opaque_sp->GetExecutableFile()); +} + +void +SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg) +{ + m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg); +} + +SBListener +SBLaunchInfo::GetListener () +{ + return SBListener(m_opaque_sp->GetListener()); +} + +void +SBLaunchInfo::SetListener (SBListener &listener) +{ + m_opaque_sp->SetListener(listener.GetSP()); +} + +uint32_t +SBLaunchInfo::GetNumArguments () +{ + return m_opaque_sp->GetArguments().GetArgumentCount(); +} + +const char * +SBLaunchInfo::GetArgumentAtIndex (uint32_t idx) +{ + return m_opaque_sp->GetArguments().GetArgumentAtIndex(idx); +} + +void +SBLaunchInfo::SetArguments (const char **argv, bool append) +{ + if (append) + { + if (argv) + m_opaque_sp->GetArguments().AppendArguments(argv); + } + else + { + if (argv) + m_opaque_sp->GetArguments().SetArguments(argv); + else + m_opaque_sp->GetArguments().Clear(); + } +} + +uint32_t +SBLaunchInfo::GetNumEnvironmentEntries () +{ + return m_opaque_sp->GetEnvironmentEntries().GetArgumentCount(); +} + +const char * +SBLaunchInfo::GetEnvironmentEntryAtIndex (uint32_t idx) +{ + return m_opaque_sp->GetEnvironmentEntries().GetArgumentAtIndex(idx); +} + +void +SBLaunchInfo::SetEnvironmentEntries (const char **envp, bool append) +{ + if (append) + { + if (envp) + m_opaque_sp->GetEnvironmentEntries().AppendArguments(envp); + } + else + { + if (envp) + m_opaque_sp->GetEnvironmentEntries().SetArguments(envp); + else + m_opaque_sp->GetEnvironmentEntries().Clear(); + } +} + +void +SBLaunchInfo::Clear () +{ + m_opaque_sp->Clear(); +} + +const char * +SBLaunchInfo::GetWorkingDirectory () const +{ + return m_opaque_sp->GetWorkingDirectory(); +} + +void +SBLaunchInfo::SetWorkingDirectory (const char *working_dir) +{ + m_opaque_sp->SetWorkingDirectory(working_dir); +} + +uint32_t +SBLaunchInfo::GetLaunchFlags () +{ + return m_opaque_sp->GetFlags().Get(); +} + +void +SBLaunchInfo::SetLaunchFlags (uint32_t flags) +{ + m_opaque_sp->GetFlags().Reset(flags); +} + +const char * +SBLaunchInfo::GetProcessPluginName () +{ + return m_opaque_sp->GetProcessPluginName(); +} + +void +SBLaunchInfo::SetProcessPluginName (const char *plugin_name) +{ + return m_opaque_sp->SetProcessPluginName (plugin_name); +} + +const char * +SBLaunchInfo::GetShell () +{ + // Constify this string so that it is saved in the string pool. Otherwise + // it would be freed when this function goes out of scope. + ConstString shell(m_opaque_sp->GetShell().GetPath().c_str()); + return shell.AsCString(); +} + +void +SBLaunchInfo::SetShell (const char * path) +{ + m_opaque_sp->SetShell (FileSpec(path, false)); +} + +uint32_t +SBLaunchInfo::GetResumeCount () +{ + return m_opaque_sp->GetResumeCount(); +} + +void +SBLaunchInfo::SetResumeCount (uint32_t c) +{ + m_opaque_sp->SetResumeCount (c); +} + +bool +SBLaunchInfo::AddCloseFileAction (int fd) +{ + return m_opaque_sp->AppendCloseFileAction(fd); +} + +bool +SBLaunchInfo::AddDuplicateFileAction (int fd, int dup_fd) +{ + return m_opaque_sp->AppendDuplicateFileAction(fd, dup_fd); +} + +bool +SBLaunchInfo::AddOpenFileAction (int fd, const char *path, bool read, bool write) +{ + return m_opaque_sp->AppendOpenFileAction(fd, path, read, write); +} + +bool +SBLaunchInfo::AddSuppressFileAction (int fd, bool read, bool write) +{ + return m_opaque_sp->AppendSuppressFileAction(fd, read, write); +} + +void +SBLaunchInfo::SetLaunchEventData (const char *data) +{ + m_opaque_sp->SetLaunchEventData (data); +} + +const char * +SBLaunchInfo::GetLaunchEventData () const +{ + return m_opaque_sp->GetLaunchEventData (); +} + +void +SBLaunchInfo::SetDetachOnError (bool enable) +{ + m_opaque_sp->SetDetachOnError (enable); +} + +bool +SBLaunchInfo::GetDetachOnError () const +{ + return m_opaque_sp->GetDetachOnError (); +} diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp index d3e769ae675b..b23891d39c21 100644 --- a/source/API/SBPlatform.cpp +++ b/source/API/SBPlatform.cpp @@ -10,6 +10,7 @@ #include "lldb/API/SBPlatform.h" #include "lldb/API/SBError.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBLaunchInfo.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Error.h" #include "lldb/Host/File.h" @@ -17,6 +18,8 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Platform.h" +#include + using namespace lldb; using namespace lldb_private; @@ -484,104 +487,108 @@ SBError SBPlatform::Put (SBFileSpec &src, SBFileSpec &dst) { - SBError sb_error; - - PlatformSP platform_sp(GetSP()); - if (platform_sp) - { - if (src.Exists()) - { - uint32_t permissions = src.ref().GetPermissions(); - if (permissions == 0) - { - if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory) - permissions = eFilePermissionsDirectoryDefault; - else - permissions = eFilePermissionsFileDefault; - } + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + if (src.Exists()) + { + uint32_t permissions = src.ref().GetPermissions(); + if (permissions == 0) + { + if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory) + permissions = eFilePermissionsDirectoryDefault; + else + permissions = eFilePermissionsFileDefault; + } - sb_error.ref() = platform_sp->PutFile(src.ref(), - dst.ref(), - permissions); - } - else - { - sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); - } - } - else - { - sb_error.SetErrorString("invalid platform"); - } - return sb_error; + return platform_sp->PutFile(src.ref(), dst.ref(), permissions); + } + + Error error; + error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); + return error; + }); } SBError SBPlatform::Install (SBFileSpec &src, SBFileSpec &dst) { - SBError sb_error; - PlatformSP platform_sp(GetSP()); - if (platform_sp) - { - if (src.Exists()) - { - sb_error.ref() = platform_sp->Install(src.ref(), dst.ref()); - } - else - { - sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); - } - } - else - { - sb_error.SetErrorString("invalid platform"); - } - return sb_error; + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + if (src.Exists()) + return platform_sp->Install(src.ref(), dst.ref()); + + Error error; + error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str()); + return error; + }); } SBError SBPlatform::Run (SBPlatformShellCommand &shell_command) +{ + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + const char *command = shell_command.GetCommand(); + if (!command) + return Error("invalid shell command (empty)"); + + const char *working_dir = shell_command.GetWorkingDirectory(); + if (working_dir == NULL) + { + working_dir = platform_sp->GetWorkingDirectory().GetCString(); + if (working_dir) + shell_command.SetWorkingDirectory(working_dir); + } + return platform_sp->RunShellCommand(command, + working_dir, + &shell_command.m_opaque_ptr->m_status, + &shell_command.m_opaque_ptr->m_signo, + &shell_command.m_opaque_ptr->m_output, + shell_command.m_opaque_ptr->m_timeout_sec); + }); +} + +SBError +SBPlatform::Launch (SBLaunchInfo &launch_info) +{ + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + return platform_sp->LaunchProcess(launch_info.ref()); + }); +} + +SBError +SBPlatform::Kill (const lldb::pid_t pid) +{ + return ExecuteConnected( + [&](const lldb::PlatformSP& platform_sp) + { + return platform_sp->KillProcess(pid); + }); +} + +SBError +SBPlatform::ExecuteConnected (const std::function& func) { SBError sb_error; - PlatformSP platform_sp(GetSP()); + const auto platform_sp(GetSP()); if (platform_sp) { if (platform_sp->IsConnected()) - { - const char *command = shell_command.GetCommand(); - if (command) - { - const char *working_dir = shell_command.GetWorkingDirectory(); - if (working_dir == NULL) - { - working_dir = platform_sp->GetWorkingDirectory().GetCString(); - if (working_dir) - shell_command.SetWorkingDirectory(working_dir); - } - sb_error.ref() = platform_sp->RunShellCommand(command, - working_dir, - &shell_command.m_opaque_ptr->m_status, - &shell_command.m_opaque_ptr->m_signo, - &shell_command.m_opaque_ptr->m_output, - shell_command.m_opaque_ptr->m_timeout_sec); - } - else - { - sb_error.SetErrorString("invalid shell command (empty)"); - } - } + sb_error.ref() = func(platform_sp); else - { sb_error.SetErrorString("not connected"); - } } else - { sb_error.SetErrorString("invalid platform"); - } - return sb_error; + + return sb_error; } SBError diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp index f5b5c08411c7..f50334f74189 100644 --- a/source/API/SBStream.cpp +++ b/source/API/SBStream.cpp @@ -70,6 +70,9 @@ SBStream::Printf (const char *format, ...) void SBStream::RedirectToFile (const char *path, bool append) { + if (path == nullptr) + return; + std::string local_data; if (m_opaque_ap.get()) { @@ -104,6 +107,9 @@ SBStream::RedirectToFile (const char *path, bool append) void SBStream::RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership) { + if (fh == nullptr) + return; + std::string local_data; if (m_opaque_ap.get()) { diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index b87b1acf45df..b13d8289560f 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -66,259 +66,6 @@ using namespace lldb_private; #define DEFAULT_DISASM_BYTE_SIZE 32 -SBLaunchInfo::SBLaunchInfo (const char **argv) : - m_opaque_sp(new ProcessLaunchInfo()) -{ - m_opaque_sp->GetFlags().Reset (eLaunchFlagDebug | eLaunchFlagDisableASLR); - if (argv && argv[0]) - m_opaque_sp->GetArguments().SetArguments(argv); -} - -SBLaunchInfo::~SBLaunchInfo() -{ -} - -lldb_private::ProcessLaunchInfo & -SBLaunchInfo::ref () -{ - return *m_opaque_sp; -} - - -uint32_t -SBLaunchInfo::GetUserID() -{ - return m_opaque_sp->GetUserID(); -} - -uint32_t -SBLaunchInfo::GetGroupID() -{ - return m_opaque_sp->GetGroupID(); -} - -bool -SBLaunchInfo::UserIDIsValid () -{ - return m_opaque_sp->UserIDIsValid(); -} - -bool -SBLaunchInfo::GroupIDIsValid () -{ - return m_opaque_sp->GroupIDIsValid(); -} - -void -SBLaunchInfo::SetUserID (uint32_t uid) -{ - m_opaque_sp->SetUserID (uid); -} - -void -SBLaunchInfo::SetGroupID (uint32_t gid) -{ - m_opaque_sp->SetGroupID (gid); -} - -SBFileSpec -SBLaunchInfo::GetExecutableFile () -{ - return SBFileSpec (m_opaque_sp->GetExecutableFile()); -} - -void -SBLaunchInfo::SetExecutableFile (SBFileSpec exe_file, bool add_as_first_arg) -{ - m_opaque_sp->SetExecutableFile(exe_file.ref(), add_as_first_arg); -} - -SBListener -SBLaunchInfo::GetListener () -{ - return SBListener(m_opaque_sp->GetListener()); -} - -void -SBLaunchInfo::SetListener (SBListener &listener) -{ - m_opaque_sp->SetListener(listener.GetSP()); -} - -uint32_t -SBLaunchInfo::GetNumArguments () -{ - return m_opaque_sp->GetArguments().GetArgumentCount(); -} - -const char * -SBLaunchInfo::GetArgumentAtIndex (uint32_t idx) -{ - return m_opaque_sp->GetArguments().GetArgumentAtIndex(idx); -} - -void -SBLaunchInfo::SetArguments (const char **argv, bool append) -{ - if (append) - { - if (argv) - m_opaque_sp->GetArguments().AppendArguments(argv); - } - else - { - if (argv) - m_opaque_sp->GetArguments().SetArguments(argv); - else - m_opaque_sp->GetArguments().Clear(); - } -} - -uint32_t -SBLaunchInfo::GetNumEnvironmentEntries () -{ - return m_opaque_sp->GetEnvironmentEntries().GetArgumentCount(); -} - -const char * -SBLaunchInfo::GetEnvironmentEntryAtIndex (uint32_t idx) -{ - return m_opaque_sp->GetEnvironmentEntries().GetArgumentAtIndex(idx); -} - -void -SBLaunchInfo::SetEnvironmentEntries (const char **envp, bool append) -{ - if (append) - { - if (envp) - m_opaque_sp->GetEnvironmentEntries().AppendArguments(envp); - } - else - { - if (envp) - m_opaque_sp->GetEnvironmentEntries().SetArguments(envp); - else - m_opaque_sp->GetEnvironmentEntries().Clear(); - } -} - -void -SBLaunchInfo::Clear () -{ - m_opaque_sp->Clear(); -} - -const char * -SBLaunchInfo::GetWorkingDirectory () const -{ - return m_opaque_sp->GetWorkingDirectory(); -} - -void -SBLaunchInfo::SetWorkingDirectory (const char *working_dir) -{ - m_opaque_sp->SetWorkingDirectory(working_dir); -} - -uint32_t -SBLaunchInfo::GetLaunchFlags () -{ - return m_opaque_sp->GetFlags().Get(); -} - -void -SBLaunchInfo::SetLaunchFlags (uint32_t flags) -{ - m_opaque_sp->GetFlags().Reset(flags); -} - -const char * -SBLaunchInfo::GetProcessPluginName () -{ - return m_opaque_sp->GetProcessPluginName(); -} - -void -SBLaunchInfo::SetProcessPluginName (const char *plugin_name) -{ - return m_opaque_sp->SetProcessPluginName (plugin_name); -} - -const char * -SBLaunchInfo::GetShell () -{ - // Constify this string so that it is saved in the string pool. Otherwise - // it would be freed when this function goes out of scope. - ConstString shell(m_opaque_sp->GetShell().GetPath().c_str()); - return shell.AsCString(); -} - -void -SBLaunchInfo::SetShell (const char * path) -{ - m_opaque_sp->SetShell (FileSpec(path, false)); -} - -uint32_t -SBLaunchInfo::GetResumeCount () -{ - return m_opaque_sp->GetResumeCount(); -} - -void -SBLaunchInfo::SetResumeCount (uint32_t c) -{ - m_opaque_sp->SetResumeCount (c); -} - -bool -SBLaunchInfo::AddCloseFileAction (int fd) -{ - return m_opaque_sp->AppendCloseFileAction(fd); -} - -bool -SBLaunchInfo::AddDuplicateFileAction (int fd, int dup_fd) -{ - return m_opaque_sp->AppendDuplicateFileAction(fd, dup_fd); -} - -bool -SBLaunchInfo::AddOpenFileAction (int fd, const char *path, bool read, bool write) -{ - return m_opaque_sp->AppendOpenFileAction(fd, path, read, write); -} - -bool -SBLaunchInfo::AddSuppressFileAction (int fd, bool read, bool write) -{ - return m_opaque_sp->AppendSuppressFileAction(fd, read, write); -} - -void -SBLaunchInfo::SetLaunchEventData (const char *data) -{ - m_opaque_sp->SetLaunchEventData (data); -} - -const char * -SBLaunchInfo::GetLaunchEventData () const -{ - return m_opaque_sp->GetLaunchEventData (); -} - -void -SBLaunchInfo::SetDetachOnError (bool enable) -{ - m_opaque_sp->SetDetachOnError (enable); -} - -bool -SBLaunchInfo::GetDetachOnError () const -{ - return m_opaque_sp->GetDetachOnError (); -} SBAttachInfo::SBAttachInfo () : m_opaque_sp (new ProcessAttachInfo()) @@ -729,6 +476,9 @@ SBTarget::Launch { Mutex::Locker api_locker (target_sp->GetAPIMutex()); + if (stop_at_entry) + launch_flags |= eLaunchFlagStopAtEntry; + if (getenv("LLDB_LAUNCH_FLAG_DISABLE_ASLR")) launch_flags |= eLaunchFlagDisableASLR; diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index 6524d10fb705..9fe0d029496c 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -1491,7 +1491,8 @@ SBThread::GetDescription (SBStream &description) const ExecutionContext exe_ctx (m_opaque_sp.get()); if (exe_ctx.HasThreadScope()) { - strm.Printf("SBThread: tid = 0x%4.4" PRIx64, exe_ctx.GetThreadPtr()->GetID()); + exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(strm, LLDB_INVALID_THREAD_ID); + //strm.Printf("SBThread: tid = 0x%4.4" PRIx64, exe_ctx.GetThreadPtr()->GetID()); } else strm.PutCString ("No value"); diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp index 8a0f5d848a3d..31a4eba8bf33 100644 --- a/source/API/SBType.cpp +++ b/source/API/SBType.cpp @@ -143,7 +143,7 @@ SBType::GetByteSize() if (!IsValid()) return 0; - return m_opaque_sp->GetClangASTType(false).GetByteSize(); + return m_opaque_sp->GetClangASTType(false).GetByteSize(nullptr); } @@ -163,6 +163,14 @@ SBType::IsArrayType() return m_opaque_sp->GetClangASTType(true).IsArrayType(nullptr, nullptr, nullptr); } +bool +SBType::IsVectorType() +{ + if (!IsValid()) + return false; + return m_opaque_sp->GetClangASTType(true).IsVectorType(nullptr, nullptr); +} + bool SBType::IsReferenceType() { @@ -220,7 +228,20 @@ SBType::GetArrayElementType() return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetClangASTType(true).GetArrayElementType()))); } -bool +SBType +SBType::GetVectorElementType () +{ + SBType type_sb; + if (IsValid()) + { + ClangASTType vector_element_type; + if (m_opaque_sp->GetClangASTType(true).IsVectorType(&vector_element_type, nullptr)) + type_sb.SetSP(TypeImplSP(new TypeImpl(vector_element_type))); + } + return type_sb; +} + +bool SBType::IsFunctionType () { if (!IsValid()) diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp index 9fe4dad01a9f..66cf46236c65 100644 --- a/source/API/SBTypeCategory.cpp +++ b/source/API/SBTypeCategory.cpp @@ -353,7 +353,7 @@ SBTypeCategory::AddTypeSummary (SBTypeNameSpecifier type_name, // this should eventually be fixed by deciding a final location in the LLDB object space for formatters if (summary.IsFunctionCode()) { - void *name_token = (void*)ConstString(type_name.GetName()).GetCString(); + const void *name_token = (const void*)ConstString(type_name.GetName()).GetCString(); const char* script = summary.GetData(); StringList input; input.SplitIntoLines(script, strlen(script)); uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers(); @@ -461,7 +461,7 @@ SBTypeCategory::AddTypeSynthetic (SBTypeNameSpecifier type_name, // this should eventually be fixed by deciding a final location in the LLDB object space for formatters if (synth.IsClassCode()) { - void *name_token = (void*)ConstString(type_name.GetName()).GetCString(); + const void *name_token = (const void*)ConstString(type_name.GetName()).GetCString(); const char* script = synth.GetData(); StringList input; input.SplitIntoLines(script, strlen(script)); uint32_t num_debuggers = lldb_private::Debugger::GetNumDebuggers(); diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp index 0d3d7ad956ee..edecb93944ad 100644 --- a/source/API/SBValue.cpp +++ b/source/API/SBValue.cpp @@ -608,7 +608,8 @@ SBValue::GetValueDidChange () lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { - result = value_sp->GetValueDidChange (); + if (value_sp->UpdateValueIfNeeded(false)) + result = value_sp->GetValueDidChange (); } if (log) log->Printf ("SBValue(%p)::GetValueDidChange() => %i", diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index bc269cdb95ac..beb0f6bc5a6e 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -60,7 +60,8 @@ Breakpoint::Breakpoint(Target &target, m_resolver_sp (resolver_sp), m_options (), m_locations (*this), - m_resolve_indirect_symbols(resolve_indirect_symbols) + m_resolve_indirect_symbols(resolve_indirect_symbols), + m_hit_count(0) { m_being_created = false; } @@ -72,7 +73,8 @@ Breakpoint::Breakpoint (Target &new_target, Breakpoint &source_bp) : m_name_list (source_bp.m_name_list), m_options (source_bp.m_options), m_locations(*this), - m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols) + m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols), + m_hit_count(0) { // Now go through and copy the filter & resolver: m_resolver_sp = source_bp.m_resolver_sp->CopyForBreakpoint(*this); @@ -207,7 +209,7 @@ Breakpoint::IgnoreCountShouldStop () uint32_t Breakpoint::GetHitCount () const { - return m_locations.GetHitCount(); + return m_hit_count; } bool diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index 11ecfecc5bc7..85233c9374cb 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -477,7 +477,22 @@ void BreakpointLocation::BumpHitCount() { if (IsEnabled()) + { + // Step our hit count, and also step the hit count of the owner. IncrementHitCount(); + m_owner.IncrementHitCount(); + } +} + +void +BreakpointLocation::UndoBumpHitCount() +{ + if (IsEnabled()) + { + // Step our hit count, and also step the hit count of the owner. + DecrementHitCount(); + m_owner.DecrementHitCount(); + } } bool diff --git a/source/Breakpoint/StoppointLocation.cpp b/source/Breakpoint/StoppointLocation.cpp index 9d8d9241253a..35e5979bd9e7 100644 --- a/source/Breakpoint/StoppointLocation.cpp +++ b/source/Breakpoint/StoppointLocation.cpp @@ -46,3 +46,10 @@ StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, uint32_t byte StoppointLocation::~StoppointLocation() { } + +void +StoppointLocation::DecrementHitCount () +{ + assert (m_hit_count > 0); + --m_hit_count; +} diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index 3d4b3aff6fff..025524b3b9a5 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -19,6 +19,7 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/OptionValueUInt64.h" @@ -140,7 +141,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed break; case 'C': - m_column = Args::StringToUInt32 (option_arg, 0); + m_column = StringConvert::ToUInt32 (option_arg, 0); break; case 'c': @@ -166,6 +167,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed case eLanguageTypeC_plus_plus: case eLanguageTypeC_plus_plus_03: case eLanguageTypeC_plus_plus_11: + case eLanguageTypeC_plus_plus_14: m_language = eLanguageTypeC_plus_plus; break; case eLanguageTypeObjC: @@ -207,7 +209,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed case 'i': { - m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_ignore_count == UINT32_MAX) error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); break; @@ -229,7 +231,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed break; case 'l': - m_line_num = Args::StringToUInt32 (option_arg, 0); + m_line_num = StringConvert::ToUInt32 (option_arg, 0); break; case 'M': @@ -276,7 +278,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed case 't' : { - m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); + m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); if (m_thread_id == LLDB_INVALID_THREAD_ID) error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); } @@ -297,7 +299,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed case 'x': { - m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_thread_id == UINT32_MAX) error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); @@ -838,7 +840,7 @@ class CommandObjectBreakpointModify : public CommandObjectParsed break; case 'i': { - m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_ignore_count == UINT32_MAX) error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); } @@ -865,7 +867,7 @@ class CommandObjectBreakpointModify : public CommandObjectParsed } else { - m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); + m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); if (m_thread_id == LLDB_INVALID_THREAD_ID) error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); else @@ -896,7 +898,7 @@ class CommandObjectBreakpointModify : public CommandObjectParsed } else { - m_thread_index = Args::StringToUInt32 (option_arg, UINT32_MAX, 0); + m_thread_index = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0); if (m_thread_id == UINT32_MAX) error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); else @@ -1555,7 +1557,7 @@ class CommandObjectBreakpointClear : public CommandObjectParsed break; case 'l': - m_line_num = Args::StringToUInt32 (option_arg, 0); + m_line_num = StringConvert::ToUInt32 (option_arg, 0); break; default: diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 8124ce1ef93b..2ba47be1ecf0 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -19,7 +19,7 @@ #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" #include "lldb/Core/SourceManager.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -76,13 +76,13 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (uint32_t option_idx, c break; case 'C': - num_lines_context = Args::StringToUInt32(option_arg, 0, 0, &success); + num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg); break; case 'c': - num_instructions = Args::StringToUInt32(option_arg, 0, 0, &success); + num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg); break; diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index b4c559c81cc5..e87399f97baa 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -15,7 +15,6 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" @@ -24,6 +23,7 @@ #include "lldb/Expression/ClangFunction.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Host/Host.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Core/Debugger.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -119,7 +119,7 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int { bool success; uint32_t result; - result = Args::StringToUInt32(option_arg, 0, 0, &success); + result = StringConvert::ToUInt32(option_arg, 0, 0, &success); if (success) timeout = result; else diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp index ce540a5c3100..4458a692a189 100644 --- a/source/Commands/CommandObjectFrame.cpp +++ b/source/Commands/CommandObjectFrame.cpp @@ -27,6 +27,7 @@ #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Host.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -119,7 +120,7 @@ class CommandObjectFrameSelect : public CommandObjectParsed switch (short_option) { case 'r': - relative_frame_offset = Args::StringToSInt32 (option_arg, INT32_MIN, 0, &success); + relative_frame_offset = StringConvert::ToSInt32 (option_arg, INT32_MIN, 0, &success); if (!success) error.SetErrorStringWithFormat ("invalid frame offset argument '%s'", option_arg); break; @@ -246,7 +247,7 @@ class CommandObjectFrameSelect : public CommandObjectParsed { const char *frame_idx_cstr = command.GetArgumentAtIndex(0); bool success = false; - frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0, &success); + frame_idx = StringConvert::ToUInt32 (frame_idx_cstr, UINT32_MAX, 0, &success); if (!success) { result.AppendErrorWithFormat ("invalid frame index argument '%s'", frame_idx_cstr); diff --git a/source/Commands/CommandObjectGUI.cpp b/source/Commands/CommandObjectGUI.cpp index 3d05335e92e4..359d6d2892d0 100644 --- a/source/Commands/CommandObjectGUI.cpp +++ b/source/Commands/CommandObjectGUI.cpp @@ -42,10 +42,22 @@ CommandObjectGUI::DoExecute (Args& args, CommandReturnObject &result) if (args.GetArgumentCount() == 0) { Debugger &debugger = m_interpreter.GetDebugger(); - IOHandlerSP io_handler_sp (new IOHandlerCursesGUI (debugger)); - if (io_handler_sp) - debugger.PushIOHandler(io_handler_sp); - result.SetStatus (eReturnStatusSuccessFinishResult); + + lldb::StreamFileSP input_sp = debugger.GetInputFile(); + if (input_sp && + input_sp->GetFile().GetIsRealTerminal() && + input_sp->GetFile().GetIsInteractive()) + { + IOHandlerSP io_handler_sp (new IOHandlerCursesGUI (debugger)); + if (io_handler_sp) + debugger.PushIOHandler(io_handler_sp); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError("the gui command requires an interactive terminal."); + result.SetStatus (eReturnStatusFailed); + } } else { diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp index f73d9d23b574..b02515e2d1e8 100644 --- a/source/Commands/CommandObjectHelp.cpp +++ b/source/Commands/CommandObjectHelp.cpp @@ -54,9 +54,10 @@ CommandObjectHelp::~CommandObjectHelp() OptionDefinition CommandObjectHelp::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Show aliases in the command list."}, + { LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Hide aliases in the command list."}, { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } + { LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Include commands prefixed with an underscore."}, + { 0, false, NULL, 0, 0, 0, NULL, 0, eArgTypeNone, NULL } }; bool @@ -75,6 +76,8 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result) cmd_types |= CommandInterpreter::eCommandTypesAliases; if (m_options.m_show_user_defined) cmd_types |= CommandInterpreter::eCommandTypesUserDef; + if (m_options.m_show_hidden) + cmd_types |= CommandInterpreter::eCommandTypesHidden; result.SetStatus (eReturnStatusSuccessFinishNoResult); m_interpreter.GetHelp (result, cmd_types); // General help @@ -136,17 +139,19 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result) else if (!sub_cmd_obj) { result.AppendErrorWithFormat("'%s' is not a known command.\n" - "Try 'help' to see a current list of commands.\n", - cmd_string.c_str()); + "Try '%shelp' to see a current list of commands.\n", + cmd_string.c_str(), + m_interpreter.GetCommandPrefix()); result.SetStatus (eReturnStatusFailed); return false; } else { result.GetOutputStream().Printf("'%s' is not a known command.\n" - "Try 'help' to see a current list of commands.\n" + "Try '%shelp' to see a current list of commands.\n" "The closest match is '%s'. Help on it follows.\n\n", cmd_string.c_str(), + m_interpreter.GetCommandPrefix(), sub_cmd_obj->GetCommandName()); } } @@ -183,8 +188,9 @@ CommandObjectHelp::DoExecute (Args& command, CommandReturnObject &result) else { result.AppendErrorWithFormat - ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n", - command.GetArgumentAtIndex(0)); + ("'%s' is not a known command.\nTry '%shelp' to see a current list of commands.\n", + command.GetArgumentAtIndex(0), + m_interpreter.GetCommandPrefix()); result.SetStatus (eReturnStatusFailed); } } diff --git a/source/Commands/CommandObjectHelp.h b/source/Commands/CommandObjectHelp.h index 6e8f9d4cbc7b..7db659c472c9 100644 --- a/source/Commands/CommandObjectHelp.h +++ b/source/Commands/CommandObjectHelp.h @@ -62,11 +62,14 @@ class CommandObjectHelp : public CommandObjectParsed switch (short_option) { case 'a': - m_show_aliases = true; + m_show_aliases = false; break; case 'u': m_show_user_defined = false; break; + case 'h': + m_show_hidden = true; + break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); break; @@ -78,8 +81,9 @@ class CommandObjectHelp : public CommandObjectParsed void OptionParsingStarting () { - m_show_aliases = false; + m_show_aliases = true; m_show_user_defined = true; + m_show_hidden = false; } const OptionDefinition* @@ -95,7 +99,8 @@ class CommandObjectHelp : public CommandObjectParsed // Instance variables to hold the values for command options. bool m_show_aliases; - bool m_show_user_defined; + bool m_show_user_defined; + bool m_show_hidden; }; virtual Options * diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp index 7d32cc6d08a5..aa09f53c792b 100644 --- a/source/Commands/CommandObjectLog.cpp +++ b/source/Commands/CommandObjectLog.cpp @@ -29,6 +29,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Debugger.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -444,7 +445,7 @@ class CommandObjectLogTimer : public CommandObjectParsed if (strcasecmp(sub_command, "enable") == 0) { bool success; - uint32_t depth = Args::StringToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success); + uint32_t depth = StringConvert::ToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success); if (success) { Timer::SetDisplayDepth (depth); diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index 6c06ec831830..dac6dd81651b 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -24,6 +24,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -566,7 +567,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed --pointer_count; } - m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(); + m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr); if (m_format_options.GetByteSizeValue() == 0) { @@ -689,7 +690,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed if (m_format_options.GetFormatValue().OptionWasSet() == false) m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); - bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue(); + bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); } else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) { @@ -1113,7 +1114,7 @@ class CommandObjectMemoryFind : public CommandObjectParsed if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get()) { uint64_t value = result_sp->GetValueAsUnsigned(0); - switch (result_sp->GetClangType().GetByteSize()) + switch (result_sp->GetClangType().GetByteSize(nullptr)) { case 1: { uint8_t byte = (uint8_t)value; @@ -1293,7 +1294,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed case 'o': { bool success; - m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success); + m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success); if (!success) { error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg); @@ -1446,7 +1447,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed if (m_memory_options.m_infile) { size_t length = SIZE_MAX; - if (item_byte_size > 0) + if (item_byte_size > 1) length = item_byte_size; lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length)); if (data_sp) @@ -1539,7 +1540,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed case eFormatPointer: // Decode hex bytes - uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success); + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str); @@ -1567,7 +1568,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed break; case eFormatBinary: - uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success); + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str); @@ -1607,7 +1608,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed break; case eFormatDecimal: - sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); + sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str); @@ -1624,7 +1625,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed break; case eFormatUnsigned: - uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str); @@ -1641,7 +1642,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed break; case eFormatOctal: - uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success); + uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success); if (!success) { result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str); diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index d176d52cb487..959c5cd1d0d7 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandOptionValidators.h" @@ -104,7 +105,7 @@ class OptionPermissions : public lldb_private::OptionGroup case 'v': { bool ok; - uint32_t perms = Args::StringToUInt32(option_arg, 777, 8, &ok); + uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok); if (!ok) error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); else @@ -248,6 +249,8 @@ class CommandObjectPlatformSelect : public CommandObjectParsed PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch)); if (platform_sp) { + m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp); + platform_sp->GetStatus (result.GetOutputStream()); result.SetStatus (eReturnStatusSuccessFinishResult); } @@ -613,7 +616,7 @@ class CommandObjectPlatformMkDir : public CommandObjectParsed std::string cmd_line; args.GetCommandString(cmd_line); uint32_t mode; - const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r'); + const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r'); if (options_permissions) mode = options_permissions->m_permissions; else @@ -682,7 +685,7 @@ class CommandObjectPlatformFOpen : public CommandObjectParsed std::string cmd_line; args.GetCommandString(cmd_line); mode_t perms; - const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r'); + const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r'); if (options_permissions) perms = options_permissions->m_permissions; else @@ -751,7 +754,7 @@ class CommandObjectPlatformFClose : public CommandObjectParsed { std::string cmd_line; args.GetCommandString(cmd_line); - const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX); + const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); Error error; bool success = platform_sp->CloseFile(fd, error); if (success) @@ -803,7 +806,7 @@ class CommandObjectPlatformFRead : public CommandObjectParsed { std::string cmd_line; args.GetCommandString(cmd_line); - const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX); + const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); std::string buffer(m_options.m_count,0); Error error; uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error); @@ -849,12 +852,12 @@ class CommandObjectPlatformFRead : public CommandObjectParsed switch (short_option) { case 'o': - m_offset = Args::StringToUInt32(option_arg, 0, 0, &success); + m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); break; case 'c': - m_count = Args::StringToUInt32(option_arg, 0, 0, &success); + m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); break; @@ -930,7 +933,7 @@ class CommandObjectPlatformFWrite : public CommandObjectParsed std::string cmd_line; args.GetCommandString(cmd_line); Error error; - const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX); + const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); uint32_t retcode = platform_sp->WriteFile (fd, m_options.m_offset, &m_options.m_data[0], @@ -977,7 +980,7 @@ class CommandObjectPlatformFWrite : public CommandObjectParsed switch (short_option) { case 'o': - m_offset = Args::StringToUInt32(option_arg, 0, 0, &success); + m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); break; @@ -1537,37 +1540,37 @@ class CommandObjectPlatformProcessList : public CommandObjectParsed switch (short_option) { case 'p': - match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); if (!success) error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg); break; case 'P': - match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); if (!success) error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg); break; case 'u': - match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); if (!success) error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg); break; case 'U': - match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); if (!success) error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg); break; case 'g': - match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); if (!success) error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg); break; case 'G': - match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); if (!success) error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg); break; @@ -1730,7 +1733,7 @@ class CommandObjectPlatformProcessInfo : public CommandObjectParsed for (size_t i=0; iGetExecutableModule(); ArchSpec old_arch_spec = target->GetArchitecture(); + ProcessSP process_sp; + Error error; if (command.GetArgumentCount()) { result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); result.SetStatus (eReturnStatusFailed); + return false; + } + + m_interpreter.UpdateExecutionContext(nullptr); + ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack")); + m_options.attach_info.SetHijackListener(listener_sp); + + // If no process info was specified, then use the target executable + // name as the process to attach to by default + if (!m_options.attach_info.ProcessInfoSpecified ()) + { + if (old_exec_module_sp) + m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename(); + + if (!m_options.attach_info.ProcessInfoSpecified ()) + { + error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option"); + } + } + + if (error.Success()) + { + if (state != eStateConnected && platform_sp != nullptr && platform_sp->CanDebugProcess()) + { + target->SetPlatform(platform_sp); + process = platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), target, error).get(); + } + else + { + if (state != eStateConnected) + { + const char *plugin_name = m_options.attach_info.GetProcessPluginName(); + process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, nullptr).get(); + if (process == nullptr) + error.SetErrorStringWithFormat("failed to create process using plugin %s", plugin_name); + } + if (process) + { + process->HijackProcessEvents(listener_sp.get()); + error = process->Attach(m_options.attach_info); + } + } + } + + if (error.Success() && process != nullptr) + { + result.SetStatus (eReturnStatusSuccessContinuingNoResult); + StreamString stream; + StateType state = process->WaitForProcessToStop (nullptr, nullptr, false, listener_sp.get(), &stream); + + process->RestoreProcessEvents(); + result.SetDidChangeProcessState (true); + + if (stream.GetData()) + result.AppendMessage(stream.GetData()); + + if (state == eStateStopped) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + const char *exit_desc = process->GetExitDescription(); + if (exit_desc) + result.AppendErrorWithFormat ("attach failed: %s", exit_desc); + else + result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); + process->Destroy(); + result.SetStatus (eReturnStatusFailed); + } } else { - if (state != eStateConnected) - { - const char *plugin_name = m_options.attach_info.GetProcessPluginName(); - process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get(); - } - - if (process) - { - Error error; - // If no process info was specified, then use the target executable - // name as the process to attach to by default - if (!m_options.attach_info.ProcessInfoSpecified ()) - { - if (old_exec_module_sp) - m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename(); - - if (!m_options.attach_info.ProcessInfoSpecified ()) - { - error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option"); - } - } - - if (error.Success()) - { - // Update the execution context so the current target and process are now selected - // in case we interrupt - m_interpreter.UpdateExecutionContext(NULL); - ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack")); - m_options.attach_info.SetHijackListener(listener_sp); - process->HijackProcessEvents(listener_sp.get()); - error = process->Attach (m_options.attach_info); - - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - StreamString stream; - StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get(), &stream); - - process->RestoreProcessEvents(); - - result.SetDidChangeProcessState (true); - - if (stream.GetData()) - result.AppendMessage(stream.GetData()); - - if (state == eStateStopped) - { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - const char *exit_desc = process->GetExitDescription(); - if (exit_desc) - result.AppendErrorWithFormat ("attach failed: %s", exit_desc); - else - result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); - process->Destroy(); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - } + result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); + result.SetStatus (eReturnStatusFailed); } - - if (result.Succeeded()) + + if (!result.Succeeded()) + return false; + + // Okay, we're done. Last step is to warn if the executable module has changed: + char new_path[PATH_MAX]; + ModuleSP new_exec_module_sp (target->GetExecutableModule()); + if (!old_exec_module_sp) { - // Okay, we're done. Last step is to warn if the executable module has changed: - char new_path[PATH_MAX]; - ModuleSP new_exec_module_sp (target->GetExecutableModule()); - if (!old_exec_module_sp) + // We might not have a module if we attached to a raw pid... + if (new_exec_module_sp) { - // We might not have a module if we attached to a raw pid... - if (new_exec_module_sp) - { - new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); - result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); - } + new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); + result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); } - else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) - { - char old_path[PATH_MAX]; - - old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); - new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); - - result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", - old_path, new_path); - } - - if (!old_arch_spec.IsValid()) - { - result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str()); - } - else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) - { - result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", - old_arch_spec.GetTriple().getTriple().c_str(), - target->GetArchitecture().GetTriple().getTriple().c_str()); - } - - // This supports the use-case scenario of immediately continuing the process once attached. - if (m_options.attach_info.GetContinueOnceAttached()) - m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); } + else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) + { + char old_path[PATH_MAX]; + + old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); + new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); + + result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", + old_path, new_path); + } + + if (!old_arch_spec.IsValid()) + { + result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str()); + } + else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) + { + result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", + old_arch_spec.GetTriple().getTriple().c_str(), + target->GetArchitecture().GetTriple().getTriple().c_str()); + } + + // This supports the use-case scenario of immediately continuing the process once attached. + if (m_options.attach_info.GetContinueOnceAttached()) + m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); + return result.Succeeded(); } @@ -714,7 +725,7 @@ class CommandObjectProcessContinue : public CommandObjectParsed switch (short_option) { case 'i': - m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success); + m_ignore = StringConvert::ToUInt32 (option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg); break; @@ -1297,7 +1308,7 @@ class CommandObjectProcessUnload : public CommandObjectParsed for (uint32_t i=0; iGetUnixSignals().GetSignalNumberFromName (signal_name); @@ -1754,7 +1765,7 @@ class CommandObjectProcessHandle : public CommandObjectParsed else { // If the value isn't 'true' or 'false', it had better be 0 or 1. - real_value = Args::StringToUInt32 (option.c_str(), 3); + real_value = StringConvert::ToUInt32 (option.c_str(), 3); if (real_value != 0 && real_value != 1) okay = false; } diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index 8fb03e69ac42..a88a9b1f0cac 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -15,7 +15,6 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileLineResolver.h" #include "lldb/Core/Module.h" @@ -24,6 +23,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" @@ -63,7 +63,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed switch (short_option) { case 'l': - start_line = Args::StringToUInt32 (option_arg, 0); + start_line = StringConvert::ToUInt32 (option_arg, 0); if (start_line == 0) error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg); break; @@ -171,13 +171,13 @@ class CommandObjectSourceList : public CommandObjectParsed switch (short_option) { case 'l': - start_line = Args::StringToUInt32 (option_arg, 0); + start_line = StringConvert::ToUInt32 (option_arg, 0); if (start_line == 0) error.SetErrorStringWithFormat("invalid line number: '%s'", option_arg); break; case 'c': - num_lines = Args::StringToUInt32 (option_arg, 0); + num_lines = StringConvert::ToUInt32 (option_arg, 0); if (num_lines == 0) error.SetErrorStringWithFormat("invalid line count: '%s'", option_arg); break; diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index 0d9ffda1e96b..9188283966f1 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -27,6 +27,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -159,7 +160,6 @@ class CommandObjectTargetCreate : public CommandObjectParsed NULL), m_option_group (interpreter), m_arch_option (), - m_platform_options(true), // Do include the "--platform" option in the platform settings by passing true m_core_file (LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, "Fullpath to a core file to use for this target."), m_platform_path (LLDB_OPT_SET_1, false, "platform-path", 'P', 0, eArgTypePath, "Path to the remote file to use for this target."), m_symbol_file (LLDB_OPT_SET_1, false, "symfile", 's', 0, eArgTypeFilename, "Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable."), @@ -180,7 +180,6 @@ class CommandObjectTargetCreate : public CommandObjectParsed m_arguments.push_back (arg); m_option_group.Append (&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); @@ -282,70 +281,83 @@ class CommandObjectTargetCreate : public CommandObjectParsed bool must_set_platform_path = false; Debugger &debugger = m_interpreter.GetDebugger(); - PlatformSP platform_sp(debugger.GetPlatformList().GetSelectedPlatform ()); - - if (remote_file) - { - // I have a remote file.. two possible cases - if (file_spec && file_spec.Exists()) - { - // if the remote file does not exist, push it there - if (!platform_sp->GetFileExists (remote_file)) - { - Error err = platform_sp->PutFile(file_spec, remote_file); - if (err.Fail()) - { - result.AppendError(err.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } - else - { - // there is no local file and we need one - // in order to make the remote ---> local transfer we need a platform - // TODO: if the user has passed in a --platform argument, use it to fetch the right platform - if (!platform_sp) - { - result.AppendError("unable to perform remote debugging without a platform"); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (file_path) - { - // copy the remote file to the local file - Error err = platform_sp->GetFile(remote_file, file_spec); - if (err.Fail()) - { - result.AppendError(err.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - else - { - // make up a local file - result.AppendError("remote --> local transfer without local path is not implemented yet"); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - } TargetSP target_sp; const char *arch_cstr = m_arch_option.GetArchitectureName(); const bool get_dependent_files = m_add_dependents.GetOptionValue().GetCurrentValue(); Error error (debugger.GetTargetList().CreateTarget (debugger, -// remote_file ? remote_file : file_spec, file_path, arch_cstr, get_dependent_files, - &m_platform_options, + NULL, target_sp)); if (target_sp) { + // Only get the platform after we create the target because we might have + // switched platforms depending on what the arguments were to CreateTarget() + // we can't rely on the selected platform. + + PlatformSP platform_sp = target_sp->GetPlatform(); + + if (remote_file) + { + if (platform_sp) + { + // I have a remote file.. two possible cases + if (file_spec && file_spec.Exists()) + { + // if the remote file does not exist, push it there + if (!platform_sp->GetFileExists (remote_file)) + { + Error err = platform_sp->PutFile(file_spec, remote_file); + if (err.Fail()) + { + result.AppendError(err.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + } + else + { + // there is no local file and we need one + // in order to make the remote ---> local transfer we need a platform + // TODO: if the user has passed in a --platform argument, use it to fetch the right platform + if (!platform_sp) + { + result.AppendError("unable to perform remote debugging without a platform"); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (file_path) + { + // copy the remote file to the local file + Error err = platform_sp->GetFile(remote_file, file_spec); + if (err.Fail()) + { + result.AppendError(err.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else + { + // make up a local file + result.AppendError("remote --> local transfer without local path is not implemented yet"); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + } + else + { + result.AppendError("no platform found for target"); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + if (symfile || remote_file) { ModuleSP module_sp (target_sp->GetExecutableModule()); @@ -426,7 +438,7 @@ class CommandObjectTargetCreate : public CommandObjectParsed } else { - result.AppendErrorWithFormat("'%s' takes exactly one executable path argument, or use the --core-file option.\n", m_cmd_name.c_str()); + result.AppendErrorWithFormat("'%s' takes exactly one executable path argument, or use the --core option.\n", m_cmd_name.c_str()); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); @@ -435,7 +447,6 @@ class CommandObjectTargetCreate : public CommandObjectParsed private: OptionGroupOptions m_option_group; OptionGroupArchitecture m_arch_option; - OptionGroupPlatform m_platform_options; OptionGroupFile m_core_file; OptionGroupFile m_platform_path; OptionGroupFile m_symbol_file; @@ -522,7 +533,7 @@ class CommandObjectTargetSelect : public CommandObjectParsed { bool success = false; const char *target_idx_arg = args.GetArgumentAtIndex(0); - uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); + uint32_t target_idx = StringConvert::ToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); if (success) { TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); @@ -629,7 +640,7 @@ class CommandObjectTargetDelete : public CommandObjectParsed for (uint32_t arg_idx = 0; success && arg_idx < argc; ++arg_idx) { const char *target_idx_arg = args.GetArgumentAtIndex(arg_idx); - uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); + uint32_t target_idx = StringConvert::ToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); if (success) { if (target_idx < num_targets) @@ -1260,7 +1271,7 @@ class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed { bool success = false; - uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); + uint32_t insert_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); if (!success) { @@ -2963,7 +2974,7 @@ class CommandObjectTargetModulesLoad : public CommandObjectTargetModulesModuleAu { ConstString const_sect_name(sect_name); bool success = false; - addr_t load_addr = Args::StringToUInt64(load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); + addr_t load_addr = StringConvert::ToUInt64(load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); if (success) { SectionSP section_sp (section_list->FindSectionByName(const_sect_name)); @@ -3890,7 +3901,7 @@ class CommandObjectTargetModulesLookup : public CommandObjectParsed break; case 'o': - m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS); + m_offset = StringConvert::ToUInt64(option_arg, LLDB_INVALID_ADDRESS); if (m_offset == LLDB_INVALID_ADDRESS) error.SetErrorStringWithFormat ("invalid offset string '%s'", option_arg); break; @@ -3910,7 +3921,7 @@ class CommandObjectTargetModulesLookup : public CommandObjectParsed break; case 'l': - m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX); + m_line_number = StringConvert::ToUInt32(option_arg, UINT32_MAX); if (m_line_number == UINT32_MAX) error.SetErrorStringWithFormat ("invalid line number string '%s'", option_arg); else if (m_line_number == 0) @@ -4078,7 +4089,7 @@ class CommandObjectTargetModulesLookup : public CommandObjectParsed if (LookupAddressInModule (m_interpreter, result.GetOutputStream(), module, - eSymbolContextEverything, + eSymbolContextEverything | (m_options.m_verbose ? eSymbolContextVariable : 0), m_options.m_addr, m_options.m_offset, m_options.m_verbose)) @@ -4873,7 +4884,7 @@ class CommandObjectTargetStopHookAdd : break; case 'e': - m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success); + m_line_end = StringConvert::ToUInt32 (option_arg, UINT_MAX, 0, &success); if (!success) { error.SetErrorStringWithFormat ("invalid end line number: \"%s\"", option_arg); @@ -4883,7 +4894,7 @@ class CommandObjectTargetStopHookAdd : break; case 'l': - m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success); + m_line_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); if (!success) { error.SetErrorStringWithFormat ("invalid start line number: \"%s\"", option_arg); @@ -4912,7 +4923,7 @@ class CommandObjectTargetStopHookAdd : break; case 't' : { - m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); + m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); if (m_thread_id == LLDB_INVALID_THREAD_ID) error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); m_thread_specified = true; @@ -4928,7 +4939,7 @@ class CommandObjectTargetStopHookAdd : break; case 'x': { - m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_thread_id == UINT32_MAX) error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); m_thread_specified = true; @@ -5233,7 +5244,7 @@ class CommandObjectTargetStopHookDelete : public CommandObjectParsed bool success; for (size_t i = 0; i < num_args; i++) { - lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); + lldb::user_id_t user_id = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); if (!success) { result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); @@ -5302,7 +5313,7 @@ class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed { for (size_t i = 0; i < num_args; i++) { - lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); + lldb::user_id_t user_id = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); if (!success) { result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index bace4e58b4ad..199d16b85205 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/State.h" #include "lldb/Core/SourceManager.h" #include "lldb/Host/Host.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" @@ -95,7 +96,7 @@ class CommandObjectIterateOverThreads : public CommandObjectParsed { bool success; - uint32_t thread_idx = Args::StringToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); + uint32_t thread_idx = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), 0, 0, &success); if (!success) { result.AppendErrorWithFormat ("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); @@ -178,7 +179,7 @@ class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads case 'c': { bool success; - int32_t input_count = Args::StringToSInt32 (option_arg, -1, 0, &success); + int32_t input_count = StringConvert::ToSInt32 (option_arg, -1, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); if (input_count < -1) @@ -190,7 +191,7 @@ class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads case 's': { bool success; - m_start = Args::StringToUInt32 (option_arg, 0, 0, &success); + m_start = StringConvert::ToUInt32 (option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); } @@ -384,7 +385,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed case 'c': { - m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + m_step_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_step_count == UINT32_MAX) error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); break; @@ -522,7 +523,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed else { const char *thread_idx_cstr = command.GetArgumentAtIndex(0); - uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); + uint32_t step_thread_idx = StringConvert::ToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32); if (step_thread_idx == LLDB_INVALID_INDEX32) { result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr); @@ -812,7 +813,7 @@ class CommandObjectThreadContinue : public CommandObjectParsed { bool success; const int base = 0; - uint32_t thread_idx = Args::StringToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); + uint32_t thread_idx = StringConvert::ToUInt32 (command.GetArgumentAtIndex(i), LLDB_INVALID_INDEX32, base, &success); if (success) { Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); @@ -984,9 +985,17 @@ class CommandObjectThreadUntil : public CommandObjectParsed switch (short_option) { + case 'a': + { + ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + lldb::addr_t tmp_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); + if (error.Success()) + m_until_addrs.push_back(tmp_addr); + } + break; case 't': { - m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32); + m_thread_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_INDEX32); if (m_thread_idx == LLDB_INVALID_INDEX32) { error.SetErrorStringWithFormat ("invalid thread index '%s'", option_arg); @@ -995,7 +1004,7 @@ class CommandObjectThreadUntil : public CommandObjectParsed break; case 'f': { - m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); + m_frame_idx = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_FRAME_ID); if (m_frame_idx == LLDB_INVALID_FRAME_ID) { error.SetErrorStringWithFormat ("invalid frame index '%s'", option_arg); @@ -1030,6 +1039,7 @@ class CommandObjectThreadUntil : public CommandObjectParsed m_thread_idx = LLDB_INVALID_THREAD_ID; m_frame_idx = 0; m_stop_others = false; + m_until_addrs.clear(); } const OptionDefinition* @@ -1040,6 +1050,7 @@ class CommandObjectThreadUntil : public CommandObjectParsed uint32_t m_step_thread_idx; bool m_stop_others; + std::vector m_until_addrs; // Options table: Required for subclasses of Options. @@ -1051,7 +1062,7 @@ class CommandObjectThreadUntil : public CommandObjectParsed CommandObjectThreadUntil (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, "thread until", - "Run the current or specified thread until it reaches a given line number or leaves the current function.", + "Run the current or specified thread until it reaches a given line number or address or leaves the current function.", NULL, eFlagRequiresThread | eFlagTryTargetAPILock | @@ -1110,22 +1121,32 @@ class CommandObjectThreadUntil : public CommandObjectParsed else { Thread *thread = NULL; - uint32_t line_number; + std::vector line_numbers; - if (command.GetArgumentCount() != 1) + if (command.GetArgumentCount() >= 1) { - result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax()); + size_t num_args = command.GetArgumentCount(); + for (size_t i = 0; i < num_args; i++) + { + uint32_t line_number; + line_number = StringConvert::ToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); + if (line_number == UINT32_MAX) + { + result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + line_numbers.push_back(line_number); + } + } + else if (m_options.m_until_addrs.empty()) + { + result.AppendErrorWithFormat ("No line number or address provided:\n%s", GetSyntax()); result.SetStatus (eReturnStatusFailed); return false; } - line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX); - if (line_number == UINT32_MAX) - { - result.AppendErrorWithFormat ("invalid line number: '%s'.\n", command.GetArgumentAtIndex(0)); - result.SetStatus (eReturnStatusFailed); - return false; - } if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { @@ -1188,27 +1209,40 @@ class CommandObjectThreadUntil : public CommandObjectParsed Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); - line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); bool all_in_function = true; - - while (index_ptr <= end_ptr) - { - LineEntry line_entry; - const bool exact = false; - index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry); - if (index_ptr == UINT32_MAX) - break; - addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); - if (address != LLDB_INVALID_ADDRESS) + line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr); + + for (uint32_t line_number : line_numbers) + { + uint32_t start_idx_ptr = index_ptr; + while (start_idx_ptr <= end_ptr) { - if (fun_addr_range.ContainsLoadAddress (address, target)) - address_list.push_back (address); - else - all_in_function = false; + LineEntry line_entry; + const bool exact = false; + start_idx_ptr = sc.comp_unit->FindLineEntry(start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); + if (start_idx_ptr == UINT32_MAX) + break; + + addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); + if (address != LLDB_INVALID_ADDRESS) + { + if (fun_addr_range.ContainsLoadAddress (address, target)) + address_list.push_back (address); + else + all_in_function = false; + } + start_idx_ptr++; } - index_ptr++; + } + + for (lldb::addr_t address : m_options.m_until_addrs) + { + if (fun_addr_range.ContainsLoadAddress (address, target)) + address_list.push_back (address); + else + all_in_function = false; } if (address_list.size() == 0) @@ -1290,7 +1324,8 @@ CommandObjectThreadUntil::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, -{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, +{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, NULL, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one"}, +{ LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1351,7 +1386,7 @@ class CommandObjectThreadSelect : public CommandObjectParsed return false; } - uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0); + uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); if (new_thread == NULL) @@ -1796,12 +1831,12 @@ class CommandObjectThreadJump : public CommandObjectParsed return Error("only one source file expected."); break; case 'l': - m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success); + m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); if (!success || m_line_num == 0) return Error("invalid line number: '%s'.", option_arg); break; case 'b': - m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success); + m_line_offset = StringConvert::ToSInt32 (option_arg, 0, 0, &success); if (!success) return Error("invalid line offset: '%s'.", option_arg); break; @@ -2120,7 +2155,7 @@ class CommandObjectThreadPlanDiscard : public CommandObjectParsed } bool success; - uint32_t thread_plan_idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); + uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); if (!success) { result.AppendErrorWithFormat("Invalid thread index: \"%s\" - should be unsigned int.", diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp index ca5fe98ccb31..bef59ca30b3c 100644 --- a/source/Commands/CommandObjectWatchpoint.cpp +++ b/source/Commands/CommandObjectWatchpoint.cpp @@ -21,6 +21,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandCompletions.h" @@ -639,7 +640,7 @@ class CommandObjectWatchpointIgnore : public CommandObjectParsed { case 'i': { - m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); if (m_ignore_count == UINT32_MAX) error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); } diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index a79becbf49c4..d449d0b21438 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -654,7 +654,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (module_sp) { SymbolContext sc; - module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); + module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything | eSymbolContextVariable, sc); if (sc.function || sc.symbol) { bool show_stop_context = true; @@ -712,7 +712,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (module_sp) { SymbolContext sc; - module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); + module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything | eSymbolContextVariable, sc); if (sc.symbol) { // If we have just a symbol make sure it is in the same section diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index e7a5e489af19..015f76bffbb5 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -765,6 +765,19 @@ ArchSpec::SetTriple (const char *triple_cstr, Platform *platform) return IsValid(); } +void +ArchSpec::MergeFrom(const ArchSpec &other) +{ + if (GetTriple().getVendor() == llvm::Triple::UnknownVendor && !TripleVendorWasSpecified()) + GetTriple().setVendor(other.GetTriple().getVendor()); + if (GetTriple().getOS() == llvm::Triple::UnknownOS && !TripleOSWasSpecified()) + GetTriple().setOS(other.GetTriple().getOS()); + if (GetTriple().getArch() == llvm::Triple::UnknownArch) + GetTriple().setArch(other.GetTriple().getArch()); + if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment) + GetTriple().setEnvironment(other.GetTriple().getEnvironment()); +} + bool ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t sub) { diff --git a/source/Core/Broadcaster.cpp b/source/Core/Broadcaster.cpp index dc37516c29c2..1cbbde20e7f6 100644 --- a/source/Core/Broadcaster.cpp +++ b/source/Core/Broadcaster.cpp @@ -303,6 +303,16 @@ Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask) return true; } +bool +Broadcaster::IsHijackedForEvent (uint32_t event_mask) +{ + Mutex::Locker event_types_locker(m_listeners_mutex); + + if (!m_hijacking_listeners.empty()) + return (event_mask & m_hijacking_masks.back()) != 0; + return false; +} + void Broadcaster::RestoreBroadcaster () { diff --git a/source/Core/ConnectionMachPort.cpp b/source/Core/ConnectionMachPort.cpp index 05ada9872b5b..fe29814be420 100644 --- a/source/Core/ConnectionMachPort.cpp +++ b/source/Core/ConnectionMachPort.cpp @@ -107,6 +107,7 @@ ConnectionMachPort::Connect (const char *s, Error *error_ptr) { if (error_ptr) error_ptr->Clear(); + m_uri.assign(s); } else { @@ -209,6 +210,7 @@ ConnectionMachPort::Disconnect (Error *error_ptr) error_ptr->SetError (kret, eErrorTypeMachKernel); m_port = MACH_PORT_TYPE_NONE; } + m_uri.clear(); return eConnectionStatusSuccess; } @@ -256,6 +258,12 @@ ConnectionMachPort::Write (const void *src, size_t src_len, ConnectionStatus &st return 0; } +std::string +ConnectionMachPort::GetURI() +{ + return m_uri; +} + ConnectionStatus ConnectionMachPort::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) { diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp index 1cbee20cd94a..d3dfa3cd8d56 100644 --- a/source/Core/ConnectionSharedMemory.cpp +++ b/source/Core/ConnectionSharedMemory.cpp @@ -107,6 +107,13 @@ ConnectionSharedMemory::Write (const void *src, size_t src_len, ConnectionStatus return 0; } +std::string +ConnectionSharedMemory::GetURI() +{ + // TODO: fix when Connect is fixed? + return ""; +} + ConnectionStatus ConnectionSharedMemory::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) { diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp index 37d24e0dec00..85f8d3c65cd9 100644 --- a/source/Core/ConstString.cpp +++ b/source/Core/ConstString.cpp @@ -11,7 +11,7 @@ #include "lldb/Host/Mutex.h" #include "llvm/ADT/StringMap.h" -#include +#include // std::once using namespace lldb_private; diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index c7342ade6cad..f25a3f41825f 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "lldb/lldb-private.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" @@ -130,24 +131,23 @@ g_language_enumerators[] = static PropertyDefinition g_properties[] = { -{ "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, -{ "disassembly-format", OptionValue::eTypeString , true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, -{ "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, -{ "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, -{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, -{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, -{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, -{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, -{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, -{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, -{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, -{ "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, -{ "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." }, -{ "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, -{ "auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, -{ "escape-non-printables", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, - - { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } +{ "auto-confirm", OptionValue::eTypeBoolean , true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." }, +{ "disassembly-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_DISASSEMBLY_FORMAT, NULL, "The default disassembly format string to use when disassembling instruction sequences." }, +{ "frame-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." }, +{ "notify-void", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." }, +{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, +{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, +{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, +{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, +{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, +{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, +{ "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, +{ "thread-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." }, +{ "use-external-editor", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Whether to use an external editor or not." }, +{ "use-color", OptionValue::eTypeBoolean , true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, +{ "auto-one-line-summaries", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, +{ "escape-non-printables", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, +{ NULL, OptionValue::eTypeInvalid , true, 0 , NULL, NULL, NULL } }; enum @@ -242,18 +242,18 @@ Debugger::GetAutoConfirm () const return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); } -const char * +const FormatEntity::Entry * Debugger::GetDisassemblyFormat() const { const uint32_t idx = ePropertyDisassemblyFormat; - return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx); } -const char * +const FormatEntity::Entry * Debugger::GetFrameFormat() const { const uint32_t idx = ePropertyFrameFormat; - return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx); } bool @@ -282,11 +282,11 @@ Debugger::SetPrompt(const char *p) GetCommandInterpreter().UpdatePrompt(new_prompt); } -const char * +const FormatEntity::Entry * Debugger::GetThreadFormat() const { const uint32_t idx = ePropertyThreadFormat; - return m_collection_sp->GetPropertyAtIndexAsString (NULL, idx, g_properties[idx].default_cstr_value); + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(NULL, idx); } lldb::ScriptLanguage @@ -927,6 +927,18 @@ Debugger::GetTopIOHandlerControlSequence(char ch) return m_input_reader_stack.GetTopIOHandlerControlSequence (ch); } +const char * +Debugger::GetIOHandlerCommandPrefix() +{ + return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); +} + +const char * +Debugger::GetIOHandlerHelpPrologue() +{ + return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); +} + void Debugger::RunIOHandler (const IOHandlerSP& reader_sp) { @@ -1214,1691 +1226,25 @@ TestPromptFormats (StackFrame *frame) } #endif -static bool -ScanFormatDescriptor (const char* var_name_begin, - const char* var_name_end, - const char** var_name_final, - const char** percent_position, - Format* custom_format, - ValueObject::ValueObjectRepresentationStyle* val_obj_display) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - *percent_position = ::strchr(var_name_begin,'%'); - if (!*percent_position || *percent_position > var_name_end) - { - if (log) - log->Printf("[ScanFormatDescriptor] no format descriptor in string, skipping"); - *var_name_final = var_name_end; - } - else - { - *var_name_final = *percent_position; - std::string format_name(*var_name_final+1, var_name_end-*var_name_final-1); - if (log) - log->Printf("[ScanFormatDescriptor] parsing %s as a format descriptor", format_name.c_str()); - if ( !FormatManager::GetFormatFromCString(format_name.c_str(), - true, - *custom_format) ) - { - if (log) - log->Printf("[ScanFormatDescriptor] %s is an unknown format", format_name.c_str()); - - switch (format_name.front()) - { - case '@': // if this is an @ sign, print ObjC description - *val_obj_display = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; - break; - case 'V': // if this is a V, print the value using the default format - *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - break; - case 'L': // if this is an L, print the location of the value - *val_obj_display = ValueObject::eValueObjectRepresentationStyleLocation; - break; - case 'S': // if this is an S, print the summary after all - *val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; - break; - case '#': // if this is a '#', print the number of children - *val_obj_display = ValueObject::eValueObjectRepresentationStyleChildrenCount; - break; - case 'T': // if this is a 'T', print the type - *val_obj_display = ValueObject::eValueObjectRepresentationStyleType; - break; - case 'N': // if this is a 'N', print the name - *val_obj_display = ValueObject::eValueObjectRepresentationStyleName; - break; - case '>': // if this is a '>', print the name - *val_obj_display = ValueObject::eValueObjectRepresentationStyleExpressionPath; - break; - default: - if (log) - log->Printf("ScanFormatDescriptor] %s is an error, leaving the previous value alone", format_name.c_str()); - break; - } - } - // a good custom format tells us to print the value using it - else - { - if (log) - log->Printf("[ScanFormatDescriptor] will display value for this VO"); - *val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - } - if (log) - log->Printf("[ScanFormatDescriptor] final format description outcome: custom_format = %d, val_obj_display = %d", - *custom_format, - *val_obj_display); - return true; -} - -static bool -ScanBracketedRange (const char* var_name_begin, - const char* var_name_end, - const char* var_name_final, - const char** open_bracket_position, - const char** separator_position, - const char** close_bracket_position, - const char** var_name_final_if_array_range, - int64_t* index_lower, - int64_t* index_higher) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - *open_bracket_position = ::strchr(var_name_begin,'['); - if (*open_bracket_position && *open_bracket_position < var_name_final) - { - *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield - *close_bracket_position = ::strchr(*open_bracket_position,']'); - // as usual, we assume that [] will come before % - //printf("trying to expand a []\n"); - *var_name_final_if_array_range = *open_bracket_position; - if (*close_bracket_position - *open_bracket_position == 1) - { - if (log) - log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); - *index_lower = 0; - } - else if (*separator_position == NULL || *separator_position > var_name_end) - { - char *end = NULL; - *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); - *index_higher = *index_lower; - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", *index_lower); - } - else if (*close_bracket_position && *close_bracket_position < var_name_end) - { - char *end = NULL; - *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); - *index_higher = ::strtoul (*separator_position+1, &end, 0); - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", *index_lower, *index_higher); - } - else - { - if (log) - log->Printf("[ScanBracketedRange] expression is erroneous, cannot extract indices out of it"); - return false; - } - if (*index_lower > *index_higher && *index_higher > 0) - { - if (log) - log->Printf("[ScanBracketedRange] swapping indices"); - int64_t temp = *index_lower; - *index_lower = *index_higher; - *index_higher = temp; - } - } - else if (log) - log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); - return true; -} - -template -static bool RunScriptFormatKeyword(Stream &s, ScriptInterpreter *script_interpreter, T t, const std::string& script_name) -{ - if (script_interpreter) - { - Error script_error; - std::string script_output; - - if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), t, script_output, script_error) && script_error.Success()) - { - s.Printf("%s", script_output.c_str()); - return true; - } - else - { - s.Printf("",script_error.AsCString()); - } - } - return false; -} - -static ValueObjectSP -ExpandIndexedExpression (ValueObject* valobj, - size_t index, - StackFrame* frame, - bool deref_pointer) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - const char* ptr_deref_format = "[%d]"; - std::string ptr_deref_buffer(10,0); - ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); - if (log) - log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); - const char* first_unparsed; - ValueObject::GetValueForExpressionPathOptions options; - ValueObject::ExpressionPathEndResultType final_value_type; - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); - ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &what_next); - if (!item) - { - if (log) - log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - } - else - { - if (log) - log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - } - return item; -} - -static inline bool -IsToken(const char *var_name_begin, const char *var) -{ - return (::strncmp (var_name_begin, var, strlen(var)) == 0); -} - -static bool -IsTokenWithFormat(const char *var_name_begin, const char *var, std::string &format, const char *default_format, - const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr) -{ - int var_len = strlen(var); - if (::strncmp (var_name_begin, var, var_len) == 0) - { - var_name_begin += var_len; - if (*var_name_begin == '}') - { - format = default_format; - return true; - } - else if (*var_name_begin == '%') - { - // Allow format specifiers: x|X|u with optional width specifiers. - // ${thread.id%x} ; hex - // ${thread.id%X} ; uppercase hex - // ${thread.id%u} ; unsigned decimal - // ${thread.id%8.8X} ; width.precision + specifier - // ${thread.id%tid} ; unsigned on FreeBSD/Linux, otherwise default_format (0x%4.4x for thread.id) - int dot_count = 0; - const char *specifier = NULL; - int width_precision_length = 0; - const char *width_precision = ++var_name_begin; - while (isdigit(*var_name_begin) || *var_name_begin == '.') - { - dot_count += (*var_name_begin == '.'); - if (dot_count > 1) - break; - var_name_begin++; - width_precision_length++; - } - - if (IsToken (var_name_begin, "tid}")) - { - Target *target = Target::GetTargetFromContexts (exe_ctx_ptr, sc_ptr); - if (target) - { - ArchSpec arch (target->GetArchitecture ()); - llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; - if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) - specifier = PRIu64; - } - if (!specifier) - { - format = default_format; - return true; - } - } - else if (IsToken (var_name_begin, "x}")) - specifier = PRIx64; - else if (IsToken (var_name_begin, "X}")) - specifier = PRIX64; - else if (IsToken (var_name_begin, "u}")) - specifier = PRIu64; - - if (specifier) - { - format = "%"; - if (width_precision_length) - format += std::string(width_precision, width_precision_length); - format += specifier; - return true; - } - } - } - return false; -} - -// Find information for the "thread.info.*" specifiers in a format string -static bool -FormatThreadExtendedInfoRecurse -( - const char *var_name_begin, - StructuredData::ObjectSP thread_info_dictionary, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - Stream &s -) -{ - bool var_success = false; - std::string token_format; - - llvm::StringRef var_name(var_name_begin); - size_t percent_idx = var_name.find('%'); - size_t close_curly_idx = var_name.find('}'); - llvm::StringRef path = var_name; - llvm::StringRef formatter = var_name; - - // 'path' will be the dot separated list of objects to transverse up until we hit - // a close curly brace, a percent sign, or an end of string. - if (percent_idx != llvm::StringRef::npos || close_curly_idx != llvm::StringRef::npos) - { - if (percent_idx != llvm::StringRef::npos && close_curly_idx != llvm::StringRef::npos) - { - if (percent_idx < close_curly_idx) - { - path = var_name.slice(0, percent_idx); - formatter = var_name.substr (percent_idx); - } - else - { - path = var_name.slice(0, close_curly_idx); - formatter = var_name.substr (close_curly_idx); - } - } - else if (percent_idx != llvm::StringRef::npos) - { - path = var_name.slice(0, percent_idx); - formatter = var_name.substr (percent_idx); - } - else if (close_curly_idx != llvm::StringRef::npos) - { - path = var_name.slice(0, close_curly_idx); - formatter = var_name.substr (close_curly_idx); - } - } - - StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); - - if (value.get()) - { - if (value->GetType() == StructuredData::Type::eTypeInteger) - { - if (IsTokenWithFormat (formatter.str().c_str(), "", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), value->GetAsInteger()->GetValue()); - var_success = true; - } - } - else if (value->GetType() == StructuredData::Type::eTypeFloat) - { - s.Printf ("%f", value->GetAsFloat()->GetValue()); - var_success = true; - } - else if (value->GetType() == StructuredData::Type::eTypeString) - { - s.Printf("%s", value->GetAsString()->GetValue().c_str()); - var_success = true; - } - else if (value->GetType() == StructuredData::Type::eTypeArray) - { - if (value->GetAsArray()->GetSize() > 0) - { - s.Printf ("%zu", value->GetAsArray()->GetSize()); - var_success = true; - } - } - else if (value->GetType() == StructuredData::Type::eTypeDictionary) - { - s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); - var_success = true; - } - } - - return var_success; -} - - -static bool -FormatPromptRecurse -( - const char *format, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s, - const char **end, - ValueObject* valobj, - bool function_changed, - bool initial_function -) -{ - ValueObject* realvalobj = NULL; // makes it super-easy to parse pointers - bool success = true; - const char *p; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - - for (p = format; *p != '\0'; ++p) - { - if (realvalobj) - { - valobj = realvalobj; - realvalobj = NULL; - } - size_t non_special_chars = ::strcspn (p, "${}\\"); - if (non_special_chars > 0) - { - if (success) - s.Write (p, non_special_chars); - p += non_special_chars; - } - - if (*p == '\0') - { - break; - } - else if (*p == '{') - { - // Start a new scope that must have everything it needs if it is to - // to make it into the final output stream "s". If you want to make - // a format that only prints out the function or symbol name if there - // is one in the symbol context you can use: - // "{function =${function.name}}" - // The first '{' starts a new scope that end with the matching '}' at - // the end of the string. The contents "function =${function.name}" - // will then be evaluated and only be output if there is a function - // or symbol with a valid name. - StreamString sub_strm; - - ++p; // Skip the '{' - - if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj, function_changed, initial_function)) - { - // The stream had all it needed - s.Write(sub_strm.GetData(), sub_strm.GetSize()); - } - if (*p != '}') - { - success = false; - break; - } - } - else if (*p == '}') - { - // End of a enclosing scope - break; - } - else if (*p == '$') - { - // We have a prompt variable to print - ++p; - if (*p == '{') - { - ++p; - const char *var_name_begin = p; - const char *var_name_end = ::strchr (p, '}'); - - if (var_name_end && var_name_begin < var_name_end) - { - // if we have already failed to parse, skip this variable - if (success) - { - const char *cstr = NULL; - std::string token_format; - Address format_addr; - - // normally "addr" means print a raw address but - // "file-addr-or-load-addr" means print a module + file addr if there's no load addr - bool print_file_addr_or_load_addr = false; - bool addr_offset_concrete_func_only = false; - bool addr_offset_print_with_no_padding = false; - bool calculate_format_addr_function_offset = false; - // Set reg_kind and reg_num to invalid values - RegisterKind reg_kind = kNumRegisterKinds; - uint32_t reg_num = LLDB_INVALID_REGNUM; - FileSpec format_file_spec; - const RegisterInfo *reg_info = NULL; - RegisterContext *reg_ctx = NULL; - bool do_deref_pointer = false; - ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; - - // Each variable must set success to true below... - bool var_success = false; - switch (var_name_begin[0]) - { - case '*': - case 'v': - case 's': - { - if (!valobj) - break; - - if (log) - log->Printf("[Debugger::FormatPrompt] initial string: %s",var_name_begin); - - // check for *var and *svar - if (*var_name_begin == '*') - { - do_deref_pointer = true; - var_name_begin++; - if (log) - log->Printf("[Debugger::FormatPrompt] found a deref, new string is: %s",var_name_begin); - } - - if (*var_name_begin == 's') - { - if (!valobj->IsSynthetic()) - valobj = valobj->GetSyntheticValue().get(); - if (!valobj) - break; - var_name_begin++; - if (log) - log->Printf("[Debugger::FormatPrompt] found a synthetic, new string is: %s",var_name_begin); - } - - // should be a 'v' by now - if (*var_name_begin != 'v') - break; - - if (log) - log->Printf("[Debugger::FormatPrompt] string I am working with: %s",var_name_begin); - - ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? - ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); - ValueObject::GetValueForExpressionPathOptions options; - options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); - ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eValueObjectRepresentationStyleSummary; - ValueObject* target = NULL; - Format custom_format = eFormatInvalid; - const char* var_name_final = NULL; - const char* var_name_final_if_array_range = NULL; - const char* close_bracket_position = NULL; - int64_t index_lower = -1; - int64_t index_higher = -1; - bool is_array_range = false; - const char* first_unparsed; - bool was_plain_var = false; - bool was_var_format = false; - bool was_var_indexed = false; - - if (!valobj) break; - // simplest case ${var}, just print valobj's value - if (IsToken (var_name_begin, "var}")) - { - was_plain_var = true; - target = valobj; - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - else if (IsToken (var_name_begin, "var.script:")) - { - var_name_begin += ::strlen("var.script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, valobj, script_name)) - var_success = true; - break; - } - else if (IsToken (var_name_begin,"var%")) - { - was_var_format = true; - // this is a variable with some custom format applied to it - const char* percent_position; - target = valobj; - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - ScanFormatDescriptor (var_name_begin, - var_name_end, - &var_name_final, - &percent_position, - &custom_format, - &val_obj_display); - } - // this is ${var.something} or multiple .something nested - else if (IsToken (var_name_begin, "var")) - { - if (IsToken (var_name_begin, "var[")) - was_var_indexed = true; - const char* percent_position; - ScanFormatDescriptor (var_name_begin, - var_name_end, - &var_name_final, - &percent_position, - &custom_format, - &val_obj_display); - - const char* open_bracket_position; - const char* separator_position; - ScanBracketedRange (var_name_begin, - var_name_end, - var_name_final, - &open_bracket_position, - &separator_position, - &close_bracket_position, - &var_name_final_if_array_range, - &index_lower, - &index_higher); - - Error error; - - std::string expr_path(var_name_final-var_name_begin-1,0); - memcpy(&expr_path[0], var_name_begin+3,var_name_final-var_name_begin-3); - - if (log) - log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); - - target = valobj->GetValueForExpressionPath(expr_path.c_str(), - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &what_next).get(); - - if (!target) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - break; - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); - } - } - else - break; - - is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || - final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); - - do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); - - if (do_deref_pointer && !is_array_range) - { - // I have not deref-ed yet, let's do it - // this happens when we are not going through GetValueForVariableExpressionPath - // to get to the target ValueObject - Error error; - target = target->Dereference(error).get(); - if (error.Fail()) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ - break; - } - do_deref_pointer = false; - } - - if (!target) - { - if (log) - log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); - break; - } - - // we do not want to use the summary for a bitfield of type T:n - // if we were originally dealing with just a T - that would get - // us into an endless recursion - if (target->IsBitfield() && was_var_indexed) - { - // TODO: check for a (T:n)-specific summary - we should still obey that - StreamString bitfield_name; - bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); - lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); - if (!DataVisualization::GetSummaryForType(type_sp)) - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - - // TODO use flags for these - const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); - bool is_array = (type_info_flags & eTypeIsArray) != 0; - bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; - bool is_aggregate = target->GetClangType().IsAggregateType(); - - if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions - { - StreamString str_temp; - if (log) - log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); - - if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) - { - // try to use the special cases - var_success = target->DumpPrintableRepresentation(str_temp, - val_obj_display, - custom_format); - if (log) - log->Printf("[Debugger::FormatPrompt] special cases did%s match", var_success ? "" : "n't"); - - // should not happen - if (var_success) - s << str_temp.GetData(); - var_success = true; - break; - } - else - { - if (was_plain_var) // if ${var} - { - s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); - } - else if (is_pointer) // if pointer, value is the address stored - { - target->DumpPrintableRepresentation (s, - val_obj_display, - custom_format, - ValueObject::ePrintableRepresentationSpecialCasesDisable); - } - var_success = true; - break; - } - } - - // if directly trying to print ${var}, and this is an aggregate, display a nice - // type @ location message - if (is_aggregate && was_plain_var) - { - s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); - var_success = true; - break; - } - - // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it - if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) - { - s << ""; - var_success = true; - break; - } - - if (!is_array_range) - { - if (log) - log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); - var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); - if (!is_array && !is_pointer) - break; - if (log) - log->Printf("[Debugger::FormatPrompt] handle as array"); - const char* special_directions = NULL; - StreamString special_directions_writer; - if (close_bracket_position && (var_name_end-close_bracket_position > 1)) - { - ConstString additional_data; - additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); - special_directions_writer.Printf("${%svar%s}", - do_deref_pointer ? "*" : "", - additional_data.GetCString()); - special_directions = special_directions_writer.GetData(); - } - - // let us display items index_lower thru index_higher of this array - s.PutChar('['); - var_success = true; - - if (index_higher < 0) - index_higher = valobj->GetNumChildren() - 1; - - uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - - for (;index_lower<=index_higher;index_lower++) - { - ValueObject* item = ExpandIndexedExpression (target, - index_lower, - exe_ctx->GetFramePtr(), - false).get(); - - if (!item) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index_lower); - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions); - } - - if (!special_directions) - var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); - else - var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item, function_changed, initial_function); - - if (--max_num_children == 0) - { - s.PutCString(", ..."); - break; - } - - if (index_lower < index_higher) - s.PutChar(','); - } - s.PutChar(']'); - } - } - break; - case 'a': - if (IsToken (var_name_begin, "addr-file-or-load}")) - { - print_file_addr_or_load_addr = true; - } - if (IsToken (var_name_begin, "addr}") - || IsToken (var_name_begin, "addr-file-or-load}")) - { - if (addr && addr->IsValid()) - { - var_success = true; - format_addr = *addr; - } - } - break; - - case 'p': - if (IsToken (var_name_begin, "process.")) - { - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - var_name_begin += ::strlen ("process."); - if (IsTokenWithFormat (var_name_begin, "id", token_format, "%" PRIu64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), process->GetID()); - var_success = true; - } - else if ((IsToken (var_name_begin, "name}")) || - (IsToken (var_name_begin, "file.basename}")) || - (IsToken (var_name_begin, "file.fullpath}"))) - { - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) - { - if (var_name_begin[0] == 'n' || var_name_begin[5] == 'f') - { - format_file_spec.GetFilename() = exe_module->GetFileSpec().GetFilename(); - var_success = (bool)format_file_spec; - } - else - { - format_file_spec = exe_module->GetFileSpec(); - var_success = (bool)format_file_spec; - } - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, process, script_name)) - var_success = true; - } - } - } - } - break; - - case 't': - if (IsToken (var_name_begin, "thread.")) - { - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - var_name_begin += ::strlen ("thread."); - if (IsTokenWithFormat (var_name_begin, "id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), thread->GetID()); - var_success = true; - } - else if (IsTokenWithFormat (var_name_begin, "protocol_id", token_format, "0x%4.4" PRIx64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), thread->GetProtocolID()); - var_success = true; - } - else if (IsTokenWithFormat (var_name_begin, "index", token_format, "%" PRIu64, exe_ctx, sc)) - { - s.Printf(token_format.c_str(), (uint64_t)thread->GetIndexID()); - var_success = true; - } - else if (IsToken (var_name_begin, "name}")) - { - cstr = thread->GetName(); - var_success = cstr && cstr[0]; - if (var_success) - s.PutCString(cstr); - } - else if (IsToken (var_name_begin, "queue}")) - { - cstr = thread->GetQueueName(); - var_success = cstr && cstr[0]; - if (var_success) - s.PutCString(cstr); - } - else if (IsToken (var_name_begin, "stop-reason}")) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - cstr = stop_info_sp->GetDescription(); - if (cstr && cstr[0]) - { - s.PutCString(cstr); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "return-value}")) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); - if (return_valobj_sp) - { - return_valobj_sp->Dump(s); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "completed-expression}")) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); - if (expression_var_sp && expression_var_sp->GetValueObject()) - { - expression_var_sp->GetValueObject()->Dump(s); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, thread, script_name)) - var_success = true; - } - else if (IsToken (var_name_begin, "info.")) - { - var_name_begin += ::strlen("info."); - StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); - if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) - { - var_success = FormatThreadExtendedInfoRecurse (var_name_begin, object_sp, sc, exe_ctx, s); - } - } - } - } - } - else if (IsToken (var_name_begin, "target.")) - { - // TODO: hookup properties -// if (!target_properties_sp) -// { -// Target *target = Target::GetTargetFromContexts (exe_ctx, sc); -// if (target) -// target_properties_sp = target->GetProperties(); -// } -// -// if (target_properties_sp) -// { -// var_name_begin += ::strlen ("target."); -// const char *end_property = strchr(var_name_begin, '}'); -// if (end_property) -// { -// ConstString property_name(var_name_begin, end_property - var_name_begin); -// std::string property_value (target_properties_sp->GetPropertyValue(property_name)); -// if (!property_value.empty()) -// { -// s.PutCString (property_value.c_str()); -// var_success = true; -// } -// } -// } - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - if (target) - { - var_name_begin += ::strlen ("target."); - if (IsToken (var_name_begin, "arch}")) - { - ArchSpec arch (target->GetArchitecture ()); - if (arch.IsValid()) - { - s.PutCString (arch.GetArchitectureName()); - var_success = true; - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, target, script_name)) - var_success = true; - } - } - } - break; - - case 'm': - if (IsToken (var_name_begin, "module.")) - { - if (sc && sc->module_sp.get()) - { - Module *module = sc->module_sp.get(); - var_name_begin += ::strlen ("module."); - - if (IsToken (var_name_begin, "file.")) - { - if (module->GetFileSpec()) - { - var_name_begin += ::strlen ("file."); - - if (IsToken (var_name_begin, "basename}")) - { - format_file_spec.GetFilename() = module->GetFileSpec().GetFilename(); - var_success = (bool)format_file_spec; - } - else if (IsToken (var_name_begin, "fullpath}")) - { - format_file_spec = module->GetFileSpec(); - var_success = (bool)format_file_spec; - } - } - } - } - } - break; - - - case 'f': - if (IsToken (var_name_begin, "file.")) - { - if (sc && sc->comp_unit != NULL) - { - var_name_begin += ::strlen ("file."); - - if (IsToken (var_name_begin, "basename}")) - { - format_file_spec.GetFilename() = sc->comp_unit->GetFilename(); - var_success = (bool)format_file_spec; - } - else if (IsToken (var_name_begin, "fullpath}")) - { - format_file_spec = *sc->comp_unit; - var_success = (bool)format_file_spec; - } - } - } - else if (IsToken (var_name_begin, "frame.")) - { - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - var_name_begin += ::strlen ("frame."); - if (IsToken (var_name_begin, "index}")) - { - s.Printf("%u", frame->GetFrameIndex()); - var_success = true; - } - else if (IsToken (var_name_begin, "pc}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_PC; - var_success = true; - } - else if (IsToken (var_name_begin, "sp}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_SP; - var_success = true; - } - else if (IsToken (var_name_begin, "fp}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_FP; - var_success = true; - } - else if (IsToken (var_name_begin, "flags}")) - { - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_FLAGS; - var_success = true; - } - else if (IsToken (var_name_begin, "reg.")) - { - reg_ctx = frame->GetRegisterContext().get(); - if (reg_ctx) - { - var_name_begin += ::strlen ("reg."); - if (var_name_begin < var_name_end) - { - std::string reg_name (var_name_begin, var_name_end); - reg_info = reg_ctx->GetRegisterInfoByName (reg_name.c_str()); - if (reg_info) - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "script:")) - { - var_name_begin += ::strlen("script:"); - std::string script_name(var_name_begin,var_name_end); - ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (RunScriptFormatKeyword (s, script_interpreter, frame, script_name)) - var_success = true; - } - } - } - } - else if (IsToken (var_name_begin, "function.")) - { - if (sc && (sc->function != NULL || sc->symbol != NULL)) - { - var_name_begin += ::strlen ("function."); - if (IsToken (var_name_begin, "id}")) - { - if (sc->function) - s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); - else - s.Printf("symbol[%u]", sc->symbol->GetID()); - - var_success = true; - } - if (IsToken (var_name_begin, "changed}") && function_changed) - { - var_success = true; - } - if (IsToken (var_name_begin, "initial-function}") && initial_function) - { - var_success = true; - } - else if (IsToken (var_name_begin, "name}")) - { - if (sc->function) - cstr = sc->function->GetName().AsCString (NULL); - else if (sc->symbol) - cstr = sc->symbol->GetName().AsCString (NULL); - if (cstr) - { - s.PutCString(cstr); - - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - if (inline_block) - { - const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - { - s.PutCString(" [inlined] "); - inline_info->GetName().Dump(&s); - } - } - } - var_success = true; - } - } - else if (IsToken (var_name_begin, "name-without-args}")) - { - ConstString name; - if (sc->function) - name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); - else if (sc->symbol) - name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); - if (name) - { - s.PutCString(name.GetCString()); - var_success = true; - } - } - else if (IsToken (var_name_begin, "name-with-args}")) - { - // Print the function name with arguments in it - - if (sc->function) - { - var_success = true; - ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; - cstr = sc->function->GetName().AsCString (NULL); - if (cstr) - { - const InlineFunctionInfo *inline_info = NULL; - VariableListSP variable_list_sp; - bool get_function_vars = true; - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - - if (inline_block) - { - get_function_vars = false; - inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - variable_list_sp = inline_block->GetBlockVariableList (true); - } - } - - if (get_function_vars) - { - variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); - } - - if (inline_info) - { - s.PutCString (cstr); - s.PutCString (" [inlined] "); - cstr = inline_info->GetName().GetCString(); - } - - VariableList args; - if (variable_list_sp) - variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); - if (args.GetSize() > 0) - { - const char *open_paren = strchr (cstr, '('); - const char *close_paren = nullptr; - const char *generic = strchr(cstr, '<'); - // if before the arguments list begins there is a template sign - // then scan to the end of the generic args before you try to find - // the arguments list - if (generic && open_paren && generic < open_paren) - { - int generic_depth = 1; - ++generic; - for (; - *generic && generic_depth > 0; - generic++) - { - if (*generic == '<') - generic_depth++; - if (*generic == '>') - generic_depth--; - } - if (*generic) - open_paren = strchr(generic, '('); - else - open_paren = nullptr; - } - if (open_paren) - { - if (IsToken (open_paren, "(anonymous namespace)")) - { - open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); - if (open_paren) - close_paren = strchr (open_paren, ')'); - } - else - close_paren = strchr (open_paren, ')'); - } - - if (open_paren) - s.Write(cstr, open_paren - cstr + 1); - else - { - s.PutCString (cstr); - s.PutChar ('('); - } - const size_t num_args = args.GetSize(); - for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) - { - std::string buffer; - - VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); - ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); - const char *var_representation = nullptr; - const char *var_name = var_value_sp->GetName().GetCString(); - if (var_value_sp->GetClangType().IsAggregateType() && - DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) - { - static StringSummaryFormat format(TypeSummaryImpl::Flags() - .SetHideItemNames(false) - .SetShowMembersOneLiner(true), - ""); - format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); - var_representation = buffer.c_str(); - } - else - var_representation = var_value_sp->GetValueAsCString(); - if (arg_idx > 0) - s.PutCString (", "); - if (var_value_sp->GetError().Success()) - { - if (var_representation) - s.Printf ("%s=%s", var_name, var_representation); - else - s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); - } - else - s.Printf ("%s=", var_name); - } - - if (close_paren) - s.PutCString (close_paren); - else - s.PutChar(')'); - - } - else - { - s.PutCString(cstr); - } - } - } - else if (sc->symbol) - { - cstr = sc->symbol->GetName().AsCString (NULL); - if (cstr) - { - s.PutCString(cstr); - var_success = true; - } - } - } - else if (IsToken (var_name_begin, "addr-offset}") - || IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) - { - if (IsToken (var_name_begin, "concrete-only-addr-offset-no-padding}")) - { - addr_offset_print_with_no_padding = true; - addr_offset_concrete_func_only = true; - } - var_success = addr != NULL; - if (var_success) - { - format_addr = *addr; - calculate_format_addr_function_offset = true; - } - } - else if (IsToken (var_name_begin, "line-offset}")) - { - var_success = sc->line_entry.range.GetBaseAddress().IsValid(); - if (var_success) - { - format_addr = sc->line_entry.range.GetBaseAddress(); - calculate_format_addr_function_offset = true; - } - } - else if (IsToken (var_name_begin, "pc-offset}")) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - var_success = frame != NULL; - if (var_success) - { - format_addr = frame->GetFrameCodeAddress(); - calculate_format_addr_function_offset = true; - } - } - } - } - break; - - case 'l': - if (IsToken (var_name_begin, "line.")) - { - if (sc && sc->line_entry.IsValid()) - { - var_name_begin += ::strlen ("line."); - if (IsToken (var_name_begin, "file.")) - { - var_name_begin += ::strlen ("file."); - - if (IsToken (var_name_begin, "basename}")) - { - format_file_spec.GetFilename() = sc->line_entry.file.GetFilename(); - var_success = (bool)format_file_spec; - } - else if (IsToken (var_name_begin, "fullpath}")) - { - format_file_spec = sc->line_entry.file; - var_success = (bool)format_file_spec; - } - } - else if (IsTokenWithFormat (var_name_begin, "number", token_format, "%" PRIu64, exe_ctx, sc)) - { - var_success = true; - s.Printf(token_format.c_str(), (uint64_t)sc->line_entry.line); - } - else if ((IsToken (var_name_begin, "start-addr}")) || - (IsToken (var_name_begin, "end-addr}"))) - { - var_success = sc && sc->line_entry.range.GetBaseAddress().IsValid(); - if (var_success) - { - format_addr = sc->line_entry.range.GetBaseAddress(); - if (var_name_begin[0] == 'e') - format_addr.Slide (sc->line_entry.range.GetByteSize()); - } - } - } - } - break; - case 'c': - if (IsToken (var_name_begin, "current-pc-arrow")) - { - if (addr && exe_ctx && exe_ctx->GetFramePtr()) - { - RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); - if (reg_ctx.get()) - { - addr_t pc_loadaddr = reg_ctx->GetPC(); - if (pc_loadaddr != LLDB_INVALID_ADDRESS) - { - Address pc; - pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); - if (pc == *addr) - { - s.Printf ("-> "); - var_success = true; - } - } - } - if (var_success == false) - { - s.Printf(" "); - var_success = true; - } - } - var_success = true; - } - break; - } - - if (var_success) - { - // If format addr is valid, then we need to print an address - if (reg_num != LLDB_INVALID_REGNUM) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - // We have a register value to display... - if (reg_num == LLDB_REGNUM_GENERIC_PC && reg_kind == eRegisterKindGeneric) - { - format_addr = frame->GetFrameCodeAddress(); - } - else - { - if (reg_ctx == NULL) - reg_ctx = frame->GetRegisterContext().get(); - - if (reg_ctx) - { - if (reg_kind != kNumRegisterKinds) - reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); - reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); - var_success = reg_info != NULL; - } - } - } - - if (reg_info != NULL) - { - RegisterValue reg_value; - var_success = reg_ctx->ReadRegister (reg_info, reg_value); - if (var_success) - { - reg_value.Dump(&s, reg_info, false, false, eFormatDefault); - } - } - - if (format_file_spec) - { - s << format_file_spec; - } - - // If format addr is valid, then we need to print an address - if (format_addr.IsValid()) - { - var_success = false; - - if (calculate_format_addr_function_offset) - { - Address func_addr; - - if (sc) - { - if (sc->function) - { - func_addr = sc->function->GetAddressRange().GetBaseAddress(); - if (sc->block && addr_offset_concrete_func_only == false) - { - // Check to make sure we aren't in an inline - // function. If we are, use the inline block - // range that contains "format_addr" since - // blocks can be discontiguous. - Block *inline_block = sc->block->GetContainingInlinedBlock (); - AddressRange inline_range; - if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) - func_addr = inline_range.GetBaseAddress(); - } - } - else if (sc->symbol && sc->symbol->ValueIsAddress()) - func_addr = sc->symbol->GetAddress(); - } - - if (func_addr.IsValid()) - { - const char *addr_offset_padding = " "; - if (addr_offset_print_with_no_padding) - { - addr_offset_padding = ""; - } - if (func_addr.GetSection() == format_addr.GetSection()) - { - addr_t func_file_addr = func_addr.GetFileAddress(); - addr_t addr_file_addr = format_addr.GetFileAddress(); - if (addr_file_addr > func_file_addr) - s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); - else if (addr_file_addr < func_file_addr) - s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); - var_success = true; - } - else - { - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - if (target) - { - addr_t func_load_addr = func_addr.GetLoadAddress (target); - addr_t addr_load_addr = format_addr.GetLoadAddress (target); - if (addr_load_addr > func_load_addr) - s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); - else if (addr_load_addr < func_load_addr) - s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); - var_success = true; - } - } - } - } - else - { - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - addr_t vaddr = LLDB_INVALID_ADDRESS; - if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) - vaddr = format_addr.GetLoadAddress (target); - if (vaddr == LLDB_INVALID_ADDRESS) - vaddr = format_addr.GetFileAddress (); - - if (vaddr != LLDB_INVALID_ADDRESS) - { - int addr_width = 0; - if (exe_ctx && target) - { - addr_width = target->GetArchitecture().GetAddressByteSize() * 2; - } - if (addr_width == 0) - addr_width = 16; - if (print_file_addr_or_load_addr) - { - format_addr.Dump (&s, exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); - } - else - { - s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); - } - var_success = true; - } - } - } - } - - if (var_success == false) - success = false; - } - p = var_name_end; - } - else - break; - } - else - { - // We got a dollar sign with no '{' after it, it must just be a dollar sign - s.PutChar(*p); - } - } - else if (*p == '\\') - { - ++p; // skip the slash - switch (*p) - { - case 'a': s.PutChar ('\a'); break; - case 'b': s.PutChar ('\b'); break; - case 'f': s.PutChar ('\f'); break; - case 'n': s.PutChar ('\n'); break; - case 'r': s.PutChar ('\r'); break; - case 't': s.PutChar ('\t'); break; - case 'v': s.PutChar ('\v'); break; - case '\'': s.PutChar ('\''); break; - case '\\': s.PutChar ('\\'); break; - case '0': - // 1 to 3 octal chars - { - // Make a string that can hold onto the initial zero char, - // up to 3 octal digits, and a terminating NULL. - char oct_str[5] = { 0, 0, 0, 0, 0 }; - - int i; - for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i) - oct_str[i] = p[i]; - - // We don't want to consume the last octal character since - // the main for loop will do this for us, so we advance p by - // one less than i (even if i is zero) - p += i - 1; - unsigned long octal_value = ::strtoul (oct_str, NULL, 8); - if (octal_value <= UINT8_MAX) - { - s.PutChar((char)octal_value); - } - } - break; - - case 'x': - // hex number in the format - if (isxdigit(p[1])) - { - ++p; // Skip the 'x' - - // Make a string that can hold onto two hex chars plus a - // NULL terminator - char hex_str[3] = { 0,0,0 }; - hex_str[0] = *p; - if (isxdigit(p[1])) - { - ++p; // Skip the first of the two hex chars - hex_str[1] = *p; - } - - unsigned long hex_value = strtoul (hex_str, NULL, 16); - if (hex_value <= UINT8_MAX) - s.PutChar ((char)hex_value); - } - else - { - s.PutChar('x'); - } - break; - - default: - // Just desensitize any other character by just printing what - // came after the '\' - s << *p; - break; - - } - - } - } - if (end) - *end = p; - return success; -} - bool -Debugger::FormatPrompt -( - const char *format, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s, - ValueObject* valobj -) -{ - bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true; - std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color); - if (format_str.length()) - format = format_str.c_str(); - return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj, false, false); -} - -bool -Debugger::FormatDisassemblerAddress (const char *format, +Debugger::FormatDisassemblerAddress (const FormatEntity::Entry *format, const SymbolContext *sc, const SymbolContext *prev_sc, const ExecutionContext *exe_ctx, const Address *addr, Stream &s) { - if (format == NULL && exe_ctx != NULL && exe_ctx->HasTargetScope()) + FormatEntity::Entry format_entry; + + if (format == NULL) { - format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + if (exe_ctx != NULL && exe_ctx->HasTargetScope()) + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + if (format == NULL) + { + FormatEntity::Parse("${addr}: ", format_entry); + format = &format_entry; + } } bool function_changed = false; bool initial_function = false; @@ -2930,7 +1276,7 @@ Debugger::FormatDisassemblerAddress (const char *format, { initial_function = true; } - return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, NULL, function_changed, initial_function); + return FormatEntity::Format(*format, s, sc, exe_ctx, addr, NULL, function_changed, initial_function); } diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp index 649f0c5bcb26..14fbee149a52 100644 --- a/source/Core/Disassembler.cpp +++ b/source/Core/Disassembler.cpp @@ -471,12 +471,7 @@ Disassembler::PrintInstructions } const bool show_bytes = (options & eOptionShowBytes) != 0; - const char *disassembly_format = "${addr-file-or-load}: "; - if (exe_ctx.HasTargetScope()) - { - disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); - } - inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, disassembly_format); + inst->Dump (&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, NULL); strm.EOL(); } else @@ -566,7 +561,7 @@ Instruction::Dump (lldb_private::Stream *s, const ExecutionContext* exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, - const char *disassembly_addr_format_spec) + const FormatEntity::Entry *disassembly_addr_format) { size_t opcode_column_width = 7; const size_t operand_column_width = 25; @@ -577,7 +572,7 @@ Instruction::Dump (lldb_private::Stream *s, if (show_address) { - Debugger::FormatDisassemblerAddress (disassembly_addr_format_spec, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss); + Debugger::FormatDisassemblerAddress (disassembly_addr_format, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss); } if (show_bytes) @@ -985,18 +980,26 @@ InstructionList::Dump (Stream *s, { const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); collection::const_iterator pos, begin, end; - const char *disassemble_format = "${addr-file-or-load}: "; - if (exe_ctx) + + const FormatEntity::Entry *disassembly_format = NULL; + FormatEntity::Entry format; + if (exe_ctx && exe_ctx->HasTargetScope()) { - disassemble_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat (); + disassembly_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat (); } + else + { + FormatEntity::Parse("${addr}: ", format); + disassembly_format = &format; + } + for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; pos != end; ++pos) { if (pos != begin) s->EOL(); - (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, NULL, NULL, disassemble_format); + (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, NULL, NULL, disassembly_format); } } @@ -1169,6 +1172,24 @@ Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) : m_flavor.assign("default"); else m_flavor.assign(flavor); + + // If this is an arm variant that can only include thumb (T16, T32) + // instructions, force the arch triple to be "thumbv.." instead of + // "armv..." + if (arch.GetTriple().getArch() == llvm::Triple::arm + && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m + || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em + || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) + { + std::string thumb_arch_name (arch.GetTriple().getArchName().str()); + // Replace "arm" with "thumb" so we get all thumb variants correct + if (thumb_arch_name.size() > 3) + { + thumb_arch_name.erase(0, 3); + thumb_arch_name.insert(0, "thumb"); + } + m_arch.SetTriple (thumb_arch_name.c_str()); + } } //---------------------------------------------------------------------- diff --git a/source/Core/Error.cpp b/source/Core/Error.cpp index 03cfd41b288d..5b0bbe273603 100644 --- a/source/Core/Error.cpp +++ b/source/Core/Error.cpp @@ -146,7 +146,7 @@ void Error::Clear () { m_code = 0; - m_type = eErrorTypeGeneric; + m_type = eErrorTypeInvalid; m_string.clear(); } diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp new file mode 100644 index 000000000000..48b2c2ddbf72 --- /dev/null +++ b/source/Core/FormatEntity.cpp @@ -0,0 +1,2511 @@ +//===-- FormatEntity.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" + +#include "lldb/Core/FormatEntity.h" + +#include "lldb/Core/Address.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/AnsiTerminal.h" + +using namespace lldb; +using namespace lldb_private; + + +enum FileKind +{ + FileError = 0, + Basename, + Dirname, + Fullpath +}; + +#define ENTRY(n,t,f) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,0,NULL, false} +#define ENTRY_VALUE(n,t,f,v) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, v,0,NULL, false} +#define ENTRY_CHILDREN(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, false} +#define ENTRY_CHILDREN_KEEP_SEP(n,t,f,c) { n, NULL, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0,llvm::array_lengthof(c),c, true} +#define ENTRY_STRING(n,s) { n, s, FormatEntity::Entry::Type::InsertString, FormatEntity::Entry::FormatType::None, 0,0, NULL, false} +static FormatEntity::Entry::Definition g_string_entry[] = +{ + ENTRY("*", ParentString, None) +}; + +static FormatEntity::Entry::Definition g_addr_entries[] = +{ + ENTRY ("load", AddressLoad , UInt64), + ENTRY ("file", AddressFile , UInt64), + ENTRY ("load", AddressLoadOrFile, UInt64), +}; + +static FormatEntity::Entry::Definition g_file_child_entries[] = +{ + ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename), + ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname), + ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath) +}; + +static FormatEntity::Entry::Definition g_frame_child_entries[] = +{ + + ENTRY ("index", FrameIndex , UInt32), + ENTRY ("pc" , FrameRegisterPC , UInt64), + ENTRY ("fp" , FrameRegisterFP , UInt64), + ENTRY ("sp" , FrameRegisterSP , UInt64), + ENTRY ("flags", FrameRegisterFlags, UInt64), + ENTRY_CHILDREN ("reg", FrameRegisterByName, UInt64, g_string_entry), +}; + +static FormatEntity::Entry::Definition g_function_child_entries[] = +{ + ENTRY ("id" , FunctionID , UInt64), + ENTRY ("name" , FunctionName , CString), + ENTRY ("name-without-args" , FunctionNameNoArgs , CString), + ENTRY ("name-with-args" , FunctionNameWithArgs , CString), + ENTRY ("addr-offset" , FunctionAddrOffset , UInt64), + ENTRY ("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, UInt64), + ENTRY ("line-offset" , FunctionLineOffset , UInt64), + ENTRY ("pc-offset" , FunctionPCOffset , UInt64) +}; + +static FormatEntity::Entry::Definition g_line_child_entries[] = +{ + ENTRY_CHILDREN("file", LineEntryFile , None , g_file_child_entries), + ENTRY("number" , LineEntryLineNumber , UInt32), + ENTRY("start-addr" , LineEntryStartAddress, UInt64), + ENTRY("end-addr" , LineEntryEndAddress , UInt64), +}; + +static FormatEntity::Entry::Definition g_module_child_entries[] = +{ + ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), +}; + +static FormatEntity::Entry::Definition g_process_child_entries[] = +{ + ENTRY ( "id" , ProcessID , UInt64 ), + ENTRY_VALUE ( "name" , ProcessFile , CString , FileKind::Basename), + ENTRY_CHILDREN ( "file" , ProcessFile , None , g_file_child_entries), +}; + +static FormatEntity::Entry::Definition g_svar_child_entries[] = +{ + ENTRY ( "*" , ParentString , None) +}; + +static FormatEntity::Entry::Definition g_var_child_entries[] = +{ + ENTRY ( "*" , ParentString , None) +}; + +static FormatEntity::Entry::Definition g_thread_child_entries[] = +{ + ENTRY ( "id" , ThreadID , UInt64 ), + ENTRY ( "protocol_id" , ThreadProtocolID , UInt64 ), + ENTRY ( "index" , ThreadIndexID , UInt32 ), + ENTRY_CHILDREN ( "info" , ThreadInfo , None , g_string_entry), + ENTRY ( "queue" , ThreadQueue , CString ), + ENTRY ( "name" , ThreadName , CString ), + ENTRY ( "stop-reason" , ThreadStopReason , CString ), + ENTRY ( "return-value" , ThreadReturnValue , CString ), + ENTRY ( "completed-expression", ThreadCompletedExpression , CString ), +}; + +static FormatEntity::Entry::Definition g_target_child_entries[] = +{ + ENTRY ( "arch" , TargetArch , CString ), +}; + +#define _TO_STR2(_val) #_val +#define _TO_STR(_val) _TO_STR2(_val) + +static FormatEntity::Entry::Definition g_ansi_fg_entries[] = +{ + ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), + ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), + ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), + ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), + ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), + ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), + ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), + ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), +}; + +static FormatEntity::Entry::Definition g_ansi_bg_entries[] = +{ + ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), + ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), + ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), + ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), + ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), + ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), + ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), + ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), +}; + +static FormatEntity::Entry::Definition g_ansi_entries[] = +{ + ENTRY_CHILDREN ( "fg" , Invalid , None , g_ansi_fg_entries), + ENTRY_CHILDREN ( "bg" , Invalid , None , g_ansi_bg_entries), + ENTRY_STRING ( "normal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), + ENTRY_STRING ( "bold" , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), + ENTRY_STRING ( "faint" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), + ENTRY_STRING ( "italic" , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), + ENTRY_STRING ( "underline" , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), + ENTRY_STRING ( "slow-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), + ENTRY_STRING ( "fast-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), + ENTRY_STRING ( "negative" , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), + ENTRY_STRING ( "conceal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), + ENTRY_STRING ( "crossed-out" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), + +}; + +static FormatEntity::Entry::Definition g_script_child_entries[] = +{ + ENTRY ( "frame" , ScriptFrame , None), + ENTRY ( "process" , ScriptProcess , None), + ENTRY ( "target" , ScriptTarget , None), + ENTRY ( "thread" , ScriptThread , None), + ENTRY ( "var" , ScriptVariable , None), + ENTRY ( "svar" , ScriptVariableSynthetic , None), + ENTRY ( "thread" , ScriptThread , None), +}; + +static FormatEntity::Entry::Definition g_top_level_entries[] = +{ + ENTRY_CHILDREN ("addr" , AddressLoadOrFile , UInt64 , g_addr_entries), + ENTRY ("addr-file-or-load" , AddressLoadOrFile , UInt64 ), + ENTRY_CHILDREN ("ansi" , Invalid , None , g_ansi_entries), + ENTRY ("current-pc-arrow" , CurrentPCArrow , CString ), + ENTRY_CHILDREN ("file" , File , CString , g_file_child_entries), + ENTRY_CHILDREN ("frame" , Invalid , None , g_frame_child_entries), + ENTRY_CHILDREN ("function" , Invalid , None , g_function_child_entries), + ENTRY_CHILDREN ("line" , Invalid , None , g_line_child_entries), + ENTRY_CHILDREN ("module" , Invalid , None , g_module_child_entries), + ENTRY_CHILDREN ("process" , Invalid , None , g_process_child_entries), + ENTRY_CHILDREN ("script" , Invalid , None , g_script_child_entries), + ENTRY_CHILDREN_KEEP_SEP ("svar" , VariableSynthetic , None , g_svar_child_entries), + ENTRY_CHILDREN ("thread" , Invalid , None , g_thread_child_entries), + ENTRY_CHILDREN ("target" , Invalid , None , g_target_child_entries), + ENTRY_CHILDREN_KEEP_SEP ("var" , Variable , None , g_var_child_entries), +}; + +static FormatEntity::Entry::Definition g_root = ENTRY_CHILDREN ("", Root, None, g_top_level_entries); + + +FormatEntity::Entry::Entry (llvm::StringRef s) : + string (s.data(), s.size()), + printf_format (), + children (), + definition (NULL), + type (Type::String), + fmt (lldb::eFormatDefault), + number (0), + deref (false) +{ +} + +FormatEntity::Entry::Entry (char ch) : + string (1, ch), + printf_format (), + children (), + definition (NULL), + type (Type::String), + fmt (lldb::eFormatDefault), + number (0), + deref (false) +{ +} + +void +FormatEntity::Entry::AppendChar (char ch) +{ + if (children.empty() || children.back().type != Entry::Type::String) + children.push_back(Entry(ch)); + else + children.back().string.append(1, ch); +} + +void +FormatEntity::Entry::AppendText (const llvm::StringRef &s) +{ + if (children.empty() || children.back().type != Entry::Type::String) + children.push_back(Entry(s)); + else + children.back().string.append(s.data(), s.size()); +} + +void +FormatEntity::Entry::AppendText (const char *cstr) +{ + return AppendText (llvm::StringRef(cstr)); +} + + +Error +FormatEntity::Parse (const llvm::StringRef &format_str, Entry &entry) +{ + entry.Clear(); + entry.type = Entry::Type::Root; + llvm::StringRef modifiable_format (format_str); + return ParseInternal (modifiable_format, entry, 0); +} + +#define ENUM_TO_CSTR(eee) case FormatEntity::Entry::Type::eee: return #eee + +const char * +FormatEntity::Entry::TypeToCString (Type t) +{ + switch (t) + { + ENUM_TO_CSTR(Invalid); + ENUM_TO_CSTR(ParentNumber); + ENUM_TO_CSTR(ParentString); + ENUM_TO_CSTR(InsertString); + ENUM_TO_CSTR(Root); + ENUM_TO_CSTR(String); + ENUM_TO_CSTR(Scope); + ENUM_TO_CSTR(Variable); + ENUM_TO_CSTR(VariableSynthetic); + ENUM_TO_CSTR(ScriptVariable); + ENUM_TO_CSTR(ScriptVariableSynthetic); + ENUM_TO_CSTR(AddressLoad); + ENUM_TO_CSTR(AddressFile); + ENUM_TO_CSTR(AddressLoadOrFile); + ENUM_TO_CSTR(ProcessID); + ENUM_TO_CSTR(ProcessFile); + ENUM_TO_CSTR(ScriptProcess); + ENUM_TO_CSTR(ThreadID); + ENUM_TO_CSTR(ThreadProtocolID); + ENUM_TO_CSTR(ThreadIndexID); + ENUM_TO_CSTR(ThreadName); + ENUM_TO_CSTR(ThreadQueue); + ENUM_TO_CSTR(ThreadStopReason); + ENUM_TO_CSTR(ThreadReturnValue); + ENUM_TO_CSTR(ThreadCompletedExpression); + ENUM_TO_CSTR(ScriptThread); + ENUM_TO_CSTR(ThreadInfo); + ENUM_TO_CSTR(TargetArch); + ENUM_TO_CSTR(ScriptTarget); + ENUM_TO_CSTR(ModuleFile); + ENUM_TO_CSTR(File); + ENUM_TO_CSTR(FrameIndex); + ENUM_TO_CSTR(FrameRegisterPC); + ENUM_TO_CSTR(FrameRegisterSP); + ENUM_TO_CSTR(FrameRegisterFP); + ENUM_TO_CSTR(FrameRegisterFlags); + ENUM_TO_CSTR(FrameRegisterByName); + ENUM_TO_CSTR(ScriptFrame); + ENUM_TO_CSTR(FunctionID); + ENUM_TO_CSTR(FunctionDidChange); + ENUM_TO_CSTR(FunctionInitialFunction); + ENUM_TO_CSTR(FunctionName); + ENUM_TO_CSTR(FunctionNameWithArgs); + ENUM_TO_CSTR(FunctionNameNoArgs); + ENUM_TO_CSTR(FunctionAddrOffset); + ENUM_TO_CSTR(FunctionAddrOffsetConcrete); + ENUM_TO_CSTR(FunctionLineOffset); + ENUM_TO_CSTR(FunctionPCOffset); + ENUM_TO_CSTR(LineEntryFile); + ENUM_TO_CSTR(LineEntryLineNumber); + ENUM_TO_CSTR(LineEntryStartAddress); + ENUM_TO_CSTR(LineEntryEndAddress); + ENUM_TO_CSTR(CurrentPCArrow); + } + return "???"; +} + +#undef ENUM_TO_CSTR + +void +FormatEntity::Entry::Dump (Stream &s, int depth) const +{ + s.Printf ("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); + if (fmt != eFormatDefault) + s.Printf ("lldb-format = %s, ", FormatManager::GetFormatAsCString (fmt)); + if (!string.empty()) + s.Printf ("string = \"%s\"", string.c_str()); + if (!printf_format.empty()) + s.Printf ("printf_format = \"%s\"", printf_format.c_str()); + if (number != 0) + s.Printf ("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); + if (deref) + s.Printf ("deref = true, "); + s.EOL(); + for (const auto &child : children) + { + child.Dump(s, depth + 1); + } +} + + +template +static bool RunScriptFormatKeyword(Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + T t, + const char *script_function_name) +{ + Target *target = Target::GetTargetFromContexts (exe_ctx, sc); + + if (target) + { + ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (script_interpreter) + { + Error error; + std::string script_output; + + if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, script_output, error) && error.Success()) + { + s.Printf("%s", script_output.c_str()); + return true; + } + else + { + s.Printf("",error.AsCString()); + } + } + } + return false; +} + +static bool +DumpAddress (Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address &addr, + bool print_file_addr_or_load_addr) +{ + Target *target = Target::GetTargetFromContexts (exe_ctx, sc); + addr_t vaddr = LLDB_INVALID_ADDRESS; + if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) + vaddr = addr.GetLoadAddress (target); + if (vaddr == LLDB_INVALID_ADDRESS) + vaddr = addr.GetFileAddress (); + + if (vaddr != LLDB_INVALID_ADDRESS) + { + int addr_width = 0; + if (exe_ctx && target) + { + addr_width = target->GetArchitecture().GetAddressByteSize() * 2; + } + if (addr_width == 0) + addr_width = 16; + if (print_file_addr_or_load_addr) + { + ExecutionContextScope *exe_scope = NULL; + if (exe_ctx) + exe_scope = exe_ctx->GetBestExecutionContextScope(); + addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); + } + else + { + s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); + } + return true; + } + return false; +} + +static bool +DumpAddressOffsetFromFunction (Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address &format_addr, + bool concrete_only, + bool no_padding) +{ + if (format_addr.IsValid()) + { + Address func_addr; + + if (sc) + { + if (sc->function) + { + func_addr = sc->function->GetAddressRange().GetBaseAddress(); + if (sc->block && !concrete_only) + { + // Check to make sure we aren't in an inline + // function. If we are, use the inline block + // range that contains "format_addr" since + // blocks can be discontiguous. + Block *inline_block = sc->block->GetContainingInlinedBlock (); + AddressRange inline_range; + if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) + func_addr = inline_range.GetBaseAddress(); + } + } + else if (sc->symbol && sc->symbol->ValueIsAddress()) + func_addr = sc->symbol->GetAddress(); + } + + if (func_addr.IsValid()) + { + const char *addr_offset_padding = no_padding ? "" : " "; + + if (func_addr.GetSection() == format_addr.GetSection()) + { + addr_t func_file_addr = func_addr.GetFileAddress(); + addr_t addr_file_addr = format_addr.GetFileAddress(); + if (addr_file_addr > func_file_addr) + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); + else if (addr_file_addr < func_file_addr) + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); + return true; + } + else + { + Target *target = Target::GetTargetFromContexts (exe_ctx, sc); + if (target) + { + addr_t func_load_addr = func_addr.GetLoadAddress (target); + addr_t addr_load_addr = format_addr.GetLoadAddress (target); + if (addr_load_addr > func_load_addr) + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); + else if (addr_load_addr < func_load_addr) + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); + return true; + } + } + } + } + return false; +} + +static bool +ScanBracketedRange (llvm::StringRef subpath, + size_t& close_bracket_index, + const char*& var_name_final_if_array_range, + int64_t& index_lower, + int64_t& index_higher) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + close_bracket_index = llvm::StringRef::npos; + const size_t open_bracket_index = subpath.find('['); + if (open_bracket_index == llvm::StringRef::npos) + { + if (log) + log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); + return false; + } + + close_bracket_index = subpath.find(']', open_bracket_index + 1); + + if (close_bracket_index == llvm::StringRef::npos) + { + if (log) + log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); + return false; + } + else + { + var_name_final_if_array_range = subpath.data() + open_bracket_index; + + if (close_bracket_index - open_bracket_index == 1) + { + if (log) + log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); + index_lower = 0; + } + else + { + const size_t separator_index = subpath.find('-', open_bracket_index + 1); + + if (separator_index == llvm::StringRef::npos) + { + const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; + index_lower = ::strtoul (index_lower_cstr, NULL, 0); + index_higher = index_lower; + if (log) + log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", index_lower); + } + else + { + const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; + const char *index_higher_cstr = subpath.data() + separator_index + 1; + index_lower = ::strtoul (index_lower_cstr, NULL, 0); + index_higher = ::strtoul (index_higher_cstr, NULL, 0); + if (log) + log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", index_lower, index_higher); + } + if (index_lower > index_higher && index_higher > 0) + { + if (log) + log->Printf("[ScanBracketedRange] swapping indices"); + const int64_t temp = index_lower; + index_lower = index_higher; + index_higher = temp; + } + } + } + return true; +} + +static bool +DumpFile (Stream &s, const FileSpec &file, FileKind file_kind) +{ + switch (file_kind) + { + case FileKind::FileError: + break; + + case FileKind::Basename: + if (file.GetFilename()) + { + s << file.GetFilename(); + return true; + } + break; + + case FileKind::Dirname: + if (file.GetDirectory()) + { + s << file.GetDirectory(); + return true; + } + break; + + case FileKind::Fullpath: + if (file) + { + s << file; + return true; + } + break; + } + return false; +} + +static bool +DumpRegister (Stream &s, + StackFrame *frame, + RegisterKind reg_kind, + uint32_t reg_num, + Format format) + +{ + if (frame) + { + RegisterContext *reg_ctx = frame->GetRegisterContext().get(); + + if (reg_ctx) + { + const uint32_t lldb_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); + if (lldb_reg_num != LLDB_INVALID_REGNUM) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (lldb_reg_num); + if (reg_info) + { + RegisterValue reg_value; + if (reg_ctx->ReadRegister (reg_info, reg_value)) + { + reg_value.Dump(&s, reg_info, false, false, format); + return true; + } + } + } + } + } + return false; +} + + +static ValueObjectSP +ExpandIndexedExpression (ValueObject* valobj, + size_t index, + StackFrame* frame, + bool deref_pointer) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + const char* ptr_deref_format = "[%d]"; + std::string ptr_deref_buffer(10,0); + ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); + if (log) + log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); + const char* first_unparsed; + ValueObject::GetValueForExpressionPathOptions options; + ValueObject::ExpressionPathEndResultType final_value_type; + ValueObject::ExpressionPathScanEndReason reason_to_stop; + ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); + ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), + &first_unparsed, + &reason_to_stop, + &final_value_type, + options, + &what_next); + if (!item) + { + if (log) + log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," + " final_value_type %d", + first_unparsed, reason_to_stop, final_value_type); + } + else + { + if (log) + log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," + " final_value_type %d", + first_unparsed, reason_to_stop, final_value_type); + } + return item; +} + +static char +ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style) +{ + switch (style) + { + case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: return '@'; + case ValueObject::eValueObjectRepresentationStyleValue: return 'V'; + case ValueObject::eValueObjectRepresentationStyleLocation: return 'L'; + case ValueObject::eValueObjectRepresentationStyleSummary: return 'S'; + case ValueObject::eValueObjectRepresentationStyleChildrenCount: return '#'; + case ValueObject::eValueObjectRepresentationStyleType: return 'T'; + case ValueObject::eValueObjectRepresentationStyleName: return 'N'; + case ValueObject::eValueObjectRepresentationStyleExpressionPath: return '>'; + } + return '\0'; +} + +static bool +DumpValue (Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const FormatEntity::Entry &entry, + ValueObject *valobj) +{ + if (valobj == NULL) + return false; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + Format custom_format = eFormatInvalid; + ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary; + + bool do_deref_pointer = entry.deref; + bool is_script = false; + switch (entry.type) + { + case FormatEntity::Entry::Type::ScriptVariable: + is_script = true; + break; + + case FormatEntity::Entry::Type::Variable: + custom_format = entry.fmt; + val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; + break; + + case FormatEntity::Entry::Type::ScriptVariableSynthetic: + is_script = true; + // Fall through + case FormatEntity::Entry::Type::VariableSynthetic: + custom_format = entry.fmt; + val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; + if (!valobj->IsSynthetic()) + { + valobj = valobj->GetSyntheticValue().get(); + if (valobj == nullptr) + return false; + } + break; + + default: + return false; + } + + if (valobj == NULL) + return false; + + ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? + ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); + ValueObject::GetValueForExpressionPathOptions options; + options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().DoAllowSyntheticChildren(); + ValueObject* target = NULL; + const char* var_name_final_if_array_range = NULL; + size_t close_bracket_index = llvm::StringRef::npos; + int64_t index_lower = -1; + int64_t index_higher = -1; + bool is_array_range = false; + const char* first_unparsed; + bool was_plain_var = false; + bool was_var_format = false; + bool was_var_indexed = false; + ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; + ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; + + if (is_script) + { + return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string.c_str()); + } + + llvm::StringRef subpath (entry.string); + // simplest case ${var}, just print valobj's value + if (entry.string.empty()) + { + if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue) + was_plain_var = true; + else + was_var_format = true; + target = valobj; + } + else // this is ${var.something} or multiple .something nested + { + if (entry.string[0] == '[') + was_var_indexed = true; + ScanBracketedRange (subpath, + close_bracket_index, + var_name_final_if_array_range, + index_lower, + index_higher); + + Error error; + + const std::string &expr_path = entry.string; + + if (log) + log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); + + target = valobj->GetValueForExpressionPath(expr_path.c_str(), + &first_unparsed, + &reason_to_stop, + &final_value_type, + options, + &what_next).get(); + + if (!target) + { + if (log) + log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," + " final_value_type %d", + first_unparsed, reason_to_stop, final_value_type); + return false; + } + else + { + if (log) + log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," + " final_value_type %d", + first_unparsed, reason_to_stop, final_value_type); + target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); + } + } + + + is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || + final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); + + do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); + + if (do_deref_pointer && !is_array_range) + { + // I have not deref-ed yet, let's do it + // this happens when we are not going through GetValueForVariableExpressionPath + // to get to the target ValueObject + Error error; + target = target->Dereference(error).get(); + if (error.Fail()) + { + if (log) + log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ + return false; + } + do_deref_pointer = false; + } + + if (!target) + { + if (log) + log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); + return false; + } + + // we do not want to use the summary for a bitfield of type T:n + // if we were originally dealing with just a T - that would get + // us into an endless recursion + if (target->IsBitfield() && was_var_indexed) + { + // TODO: check for a (T:n)-specific summary - we should still obey that + StreamString bitfield_name; + bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); + lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); + if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp)) + val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; + } + + // TODO use flags for these + const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); + bool is_array = (type_info_flags & eTypeIsArray) != 0; + bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; + bool is_aggregate = target->GetClangType().IsAggregateType(); + + if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions + { + StreamString str_temp; + if (log) + log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); + + if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) + { + // try to use the special cases + bool success = target->DumpPrintableRepresentation(str_temp, + val_obj_display, + custom_format); + if (log) + log->Printf("[Debugger::FormatPrompt] special cases did%s match", success ? "" : "n't"); + + // should not happen + if (success) + s << str_temp.GetData(); + return true; + } + else + { + if (was_plain_var) // if ${var} + { + s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); + } + else if (is_pointer) // if pointer, value is the address stored + { + target->DumpPrintableRepresentation (s, + val_obj_display, + custom_format, + ValueObject::ePrintableRepresentationSpecialCasesDisable); + } + return true; + } + } + + // if directly trying to print ${var}, and this is an aggregate, display a nice + // type @ location message + if (is_aggregate && was_plain_var) + { + s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); + return true; + } + + // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it + if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) + { + s << ""; + return true; + } + + if (!is_array_range) + { + if (log) + log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); + return target->DumpPrintableRepresentation(s,val_obj_display, custom_format); + } + else + { + if (log) + log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); + if (!is_array && !is_pointer) + return false; + if (log) + log->Printf("[Debugger::FormatPrompt] handle as array"); + llvm::StringRef special_directions; + if (close_bracket_index != llvm::StringRef::npos && subpath.size() > close_bracket_index) + { + ConstString additional_data (subpath.drop_front(close_bracket_index+1)); + StreamString special_directions_stream; + special_directions_stream.Printf("${%svar%s", + do_deref_pointer ? "*" : "", + additional_data.GetCString()); + + if (entry.fmt != eFormatDefault) + { + const char format_char = FormatManager::GetFormatAsFormatChar(entry.fmt); + if (format_char != '\0') + special_directions_stream.Printf("%%%c", format_char); + else + { + const char *format_cstr = FormatManager::GetFormatAsCString(entry.fmt); + special_directions_stream.Printf("%%%s", format_cstr); + } + } + else if (entry.number != 0) + { + const char style_char = ConvertValueObjectStyleToChar ((ValueObject::ValueObjectRepresentationStyle)entry.number); + if (style_char) + special_directions_stream.Printf("%%%c", style_char); + } + special_directions_stream.PutChar('}'); + special_directions = llvm::StringRef(special_directions_stream.GetString()); + } + + // let us display items index_lower thru index_higher of this array + s.PutChar('['); + + if (index_higher < 0) + index_higher = valobj->GetNumChildren() - 1; + + uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + + bool success = true; + for (int64_t index = index_lower;index<=index_higher; ++index) + { + ValueObject* item = ExpandIndexedExpression (target, + index, + exe_ctx->GetFramePtr(), + false).get(); + + if (!item) + { + if (log) + log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index); + } + else + { + if (log) + log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions.data() ? special_directions.data() : ""); + } + + if (special_directions.empty()) + { + success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); + } + else + { + success &= FormatEntity::FormatStringRef(special_directions, s, sc, exe_ctx, NULL, item, false, false); + } + + if (--max_num_children == 0) + { + s.PutCString(", ..."); + break; + } + + if (index < index_higher) + s.PutChar(','); + } + s.PutChar(']'); + return success; + } + +} + +static bool +DumpRegister (Stream &s, + StackFrame *frame, + const char *reg_name, + Format format) + +{ + if (frame) + { + RegisterContext *reg_ctx = frame->GetRegisterContext().get(); + + if (reg_ctx) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); + if (reg_info) + { + RegisterValue reg_value; + if (reg_ctx->ReadRegister (reg_info, reg_value)) + { + reg_value.Dump(&s, reg_info, false, false, format); + return true; + } + } + } + } + return false; +} + +static bool +FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry, + const StructuredData::ObjectSP &thread_info_dictionary, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + Stream &s) +{ + llvm::StringRef path(entry.string); + + StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); + + if (value.get()) + { + if (value->GetType() == StructuredData::Type::eTypeInteger) + { + const char *token_format = "0x%4.4" PRIx64; + if (!entry.printf_format.empty()) + token_format = entry.printf_format.c_str(); + s.Printf(token_format, value->GetAsInteger()->GetValue()); + return true; + } + else if (value->GetType() == StructuredData::Type::eTypeFloat) + { + s.Printf ("%f", value->GetAsFloat()->GetValue()); + return true; + } + else if (value->GetType() == StructuredData::Type::eTypeString) + { + s.Printf("%s", value->GetAsString()->GetValue().c_str()); + return true; + } + else if (value->GetType() == StructuredData::Type::eTypeArray) + { + if (value->GetAsArray()->GetSize() > 0) + { + s.Printf ("%zu", value->GetAsArray()->GetSize()); + return true; + } + } + else if (value->GetType() == StructuredData::Type::eTypeDictionary) + { + s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); + return true; + } + } + + return false; +} + + +static inline bool +IsToken(const char *var_name_begin, const char *var) +{ + return (::strncmp (var_name_begin, var, strlen(var)) == 0); +} + +bool +FormatEntity::FormatStringRef (const llvm::StringRef &format_str, + Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + ValueObject* valobj, + bool function_changed, + bool initial_function) +{ + if (!format_str.empty()) + { + FormatEntity::Entry root; + Error error = FormatEntity::Parse(format_str, root); + if (error.Success()) + { + return FormatEntity::Format (root, + s, + sc, + exe_ctx, + addr, + valobj, + function_changed, + initial_function); + } + } + return false; + +} +bool +FormatEntity::FormatCString (const char *format, + Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + ValueObject* valobj, + bool function_changed, + bool initial_function) +{ + if (format && format[0]) + { + FormatEntity::Entry root; + llvm::StringRef format_str(format); + Error error = FormatEntity::Parse(format_str, root); + if (error.Success()) + { + return FormatEntity::Format (root, + s, + sc, + exe_ctx, + addr, + valobj, + function_changed, + initial_function); + } + } + return false; +} + +bool +FormatEntity::Format (const Entry &entry, + Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + ValueObject* valobj, + bool function_changed, + bool initial_function) +{ + switch (entry.type) + { + case Entry::Type::Invalid: + case Entry::Type::ParentNumber: // Only used for FormatEntity::Entry::Definition encoding + case Entry::Type::ParentString: // Only used for FormatEntity::Entry::Definition encoding + case Entry::Type::InsertString: // Only used for FormatEntity::Entry::Definition encoding + return false; + + case Entry::Type::Root: + for (const auto &child : entry.children) + { + if (Format (child, + s, + sc, + exe_ctx, + addr, + valobj, + function_changed, + initial_function) == false) + { + return false; // If any item of root fails, then the formatting fails + } + } + return true; // Only return true if all items succeeded + + case Entry::Type::String: + s.PutCString(entry.string.c_str()); + return true; + + case Entry::Type::Scope: + { + StreamString scope_stream; + bool success = false; + for (const auto &child : entry.children) + { + success = Format (child, scope_stream, sc, exe_ctx, addr, valobj, function_changed, initial_function); + if (!success) + break; + } + // Only if all items in a scope succeed, then do we + // print the output into the main stream + if (success) + s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); + } + return true; // Scopes always successfully print themselves + + case Entry::Type::Variable: + case Entry::Type::VariableSynthetic: + case Entry::Type::ScriptVariable: + case Entry::Type::ScriptVariableSynthetic: + if (DumpValue(s, sc, exe_ctx, entry, valobj)) + return true; + return false; + + case Entry::Type::AddressFile: + case Entry::Type::AddressLoad: + case Entry::Type::AddressLoadOrFile: + if (addr && addr->IsValid() && DumpAddress(s, sc, exe_ctx, *addr, entry.type == Entry::Type::AddressLoadOrFile)) + return true; + return false; + + case Entry::Type::ProcessID: + if (exe_ctx) + { + Process *process = exe_ctx->GetProcessPtr(); + if (process) + { + const char *format = "%" PRIu64; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, process->GetID()); + return true; + } + } + return false; + + case Entry::Type::ProcessFile: + if (exe_ctx) + { + Process *process = exe_ctx->GetProcessPtr(); + if (process) + { + Module *exe_module = process->GetTarget().GetExecutableModulePointer(); + if (exe_module) + { + if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) + return true; + } + } + } + return false; + + case Entry::Type::ScriptProcess: + if (exe_ctx) + { + Process *process = exe_ctx->GetProcessPtr(); + if (process) + return RunScriptFormatKeyword (s, sc, exe_ctx, process, entry.string.c_str()); + } + return false; + + + case Entry::Type::ThreadID: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + const char *format = "0x%4.4" PRIx64; + if (!entry.printf_format.empty()) + { + // Watch for the special "tid" format... + if (entry.printf_format == "tid") + { + bool handled = false; + Target &target = thread->GetProcess()->GetTarget(); + ArchSpec arch (target.GetArchitecture ()); + llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; + if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) + { + handled = true; + format = "%" PRIu64; + } + } + else + { + format = entry.printf_format.c_str(); + } + } + s.Printf(format, thread->GetID()); + return true; + } + } + return false; + + case Entry::Type::ThreadProtocolID: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + const char *format = "0x%4.4" PRIx64; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, thread->GetProtocolID()); + return true; + } + } + return false; + + case Entry::Type::ThreadIndexID: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, thread->GetIndexID()); + return true; + } + } + return false; + + case Entry::Type::ThreadName: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + const char *cstr = thread->GetName(); + if (cstr && cstr[0]) + { + s.PutCString(cstr); + return true; + } + } + } + return false; + + case Entry::Type::ThreadQueue: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + const char *cstr = thread->GetQueueName(); + if (cstr && cstr[0]) + { + s.PutCString(cstr); + return true; + } + } + } + return false; + + case Entry::Type::ThreadStopReason: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + StopInfoSP stop_info_sp = thread->GetStopInfo (); + if (stop_info_sp && stop_info_sp->IsValid()) + { + const char *cstr = stop_info_sp->GetDescription(); + if (cstr && cstr[0]) + { + s.PutCString(cstr); + return true; + } + } + } + } + return false; + + case Entry::Type::ThreadReturnValue: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + StopInfoSP stop_info_sp = thread->GetStopInfo (); + if (stop_info_sp && stop_info_sp->IsValid()) + { + ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); + if (return_valobj_sp) + { + return_valobj_sp->Dump(s); + return true; + } + } + } + } + return false; + + case Entry::Type::ThreadCompletedExpression: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + StopInfoSP stop_info_sp = thread->GetStopInfo (); + if (stop_info_sp && stop_info_sp->IsValid()) + { + ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); + if (expression_var_sp && expression_var_sp->GetValueObject()) + { + expression_var_sp->GetValueObject()->Dump(s); + return true; + } + } + } + } + return false; + + case Entry::Type::ScriptThread: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + return RunScriptFormatKeyword (s, sc, exe_ctx, thread, entry.string.c_str()); + } + return false; + + case Entry::Type::ThreadInfo: + if (exe_ctx) + { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + { + StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); + if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) + { + if (FormatThreadExtendedInfoRecurse (entry, object_sp, sc, exe_ctx, s)) + return true; + } + } + } + return false; + + case Entry::Type::TargetArch: + if (exe_ctx) + { + Target *target = exe_ctx->GetTargetPtr(); + if (target) + { + const ArchSpec &arch = target->GetArchitecture (); + if (arch.IsValid()) + { + s.PutCString (arch.GetArchitectureName()); + return true; + } + } + } + return false; + + case Entry::Type::ScriptTarget: + if (exe_ctx) + { + Target *target = exe_ctx->GetTargetPtr(); + if (target) + return RunScriptFormatKeyword (s, sc, exe_ctx, target, entry.string.c_str()); + } + return false; + + case Entry::Type::ModuleFile: + if (sc) + { + Module *module = sc->module_sp.get(); + if (module) + { + if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) + return true; + } + } + return false; + + case Entry::Type::File: + if (sc) + { + CompileUnit *cu = sc->comp_unit; + if (cu) + { + // CompileUnit is a FileSpec + if (DumpFile(s, *cu, (FileKind)entry.number)) + return true; + } + } + return false; + + case Entry::Type::FrameIndex: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, frame->GetFrameIndex()); + return true; + } + } + return false; + + case Entry::Type::FrameRegisterPC: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + const Address &pc_addr = frame->GetFrameCodeAddress(); + if (pc_addr.IsValid()) + { + if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) + return true; + } + } + } + return false; + + case Entry::Type::FrameRegisterSP: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (lldb::Format)entry.number)) + return true; + } + } + return false; + + case Entry::Type::FrameRegisterFP: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, (lldb::Format)entry.number)) + return true; + } + } + return false; + + case Entry::Type::FrameRegisterFlags: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) + return true; + } + } + return false; + + + case Entry::Type::FrameRegisterByName: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + if (DumpRegister (s, frame, entry.string.c_str(), (lldb::Format)entry.number)) + return true; + } + } + return false; + + case Entry::Type::ScriptFrame: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + return RunScriptFormatKeyword (s, sc, exe_ctx, frame, entry.string.c_str()); + } + return false; + + case Entry::Type::FunctionID: + if (sc) + { + if (sc->function) + { + s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); + return true; + } + else if (sc->symbol) + { + s.Printf("symbol[%u]", sc->symbol->GetID()); + return true; + } + } + return false; + + case Entry::Type::FunctionDidChange: + return function_changed; + + case Entry::Type::FunctionInitialFunction: + return initial_function; + + case Entry::Type::FunctionName: + { + const char *name = NULL; + if (sc->function) + name = sc->function->GetName().AsCString (NULL); + else if (sc->symbol) + name = sc->symbol->GetName().AsCString (NULL); + if (name) + { + s.PutCString(name); + + if (sc->block) + { + Block *inline_block = sc->block->GetContainingInlinedBlock (); + if (inline_block) + { + const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); + if (inline_info) + { + s.PutCString(" [inlined] "); + inline_info->GetName().Dump(&s); + } + } + } + return true; + } + } + return false; + + case Entry::Type::FunctionNameNoArgs: + { + ConstString name; + if (sc->function) + name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); + else if (sc->symbol) + name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments); + if (name) + { + s.PutCString(name.GetCString()); + return true; + } + } + return false; + + case Entry::Type::FunctionNameWithArgs: + { + // Print the function name with arguments in it + if (sc->function) + { + ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; + const char *cstr = sc->function->GetName().AsCString (NULL); + if (cstr) + { + const InlineFunctionInfo *inline_info = NULL; + VariableListSP variable_list_sp; + bool get_function_vars = true; + if (sc->block) + { + Block *inline_block = sc->block->GetContainingInlinedBlock (); + + if (inline_block) + { + get_function_vars = false; + inline_info = sc->block->GetInlinedFunctionInfo(); + if (inline_info) + variable_list_sp = inline_block->GetBlockVariableList (true); + } + } + + if (get_function_vars) + { + variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); + } + + if (inline_info) + { + s.PutCString (cstr); + s.PutCString (" [inlined] "); + cstr = inline_info->GetName().GetCString(); + } + + VariableList args; + if (variable_list_sp) + variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); + if (args.GetSize() > 0) + { + const char *open_paren = strchr (cstr, '('); + const char *close_paren = nullptr; + const char *generic = strchr(cstr, '<'); + // if before the arguments list begins there is a template sign + // then scan to the end of the generic args before you try to find + // the arguments list + if (generic && open_paren && generic < open_paren) + { + int generic_depth = 1; + ++generic; + for (; + *generic && generic_depth > 0; + generic++) + { + if (*generic == '<') + generic_depth++; + if (*generic == '>') + generic_depth--; + } + if (*generic) + open_paren = strchr(generic, '('); + else + open_paren = nullptr; + } + if (open_paren) + { + if (IsToken (open_paren, "(anonymous namespace)")) + { + open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); + if (open_paren) + close_paren = strchr (open_paren, ')'); + } + else + close_paren = strchr (open_paren, ')'); + } + + if (open_paren) + s.Write(cstr, open_paren - cstr + 1); + else + { + s.PutCString (cstr); + s.PutChar ('('); + } + const size_t num_args = args.GetSize(); + for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) + { + std::string buffer; + + VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); + ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); + const char *var_representation = nullptr; + const char *var_name = var_value_sp->GetName().GetCString(); + if (var_value_sp->GetClangType().IsAggregateType() && + DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) + { + static StringSummaryFormat format(TypeSummaryImpl::Flags() + .SetHideItemNames(false) + .SetShowMembersOneLiner(true), + ""); + format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); + var_representation = buffer.c_str(); + } + else + var_representation = var_value_sp->GetValueAsCString(); + if (arg_idx > 0) + s.PutCString (", "); + if (var_value_sp->GetError().Success()) + { + if (var_representation) + s.Printf ("%s=%s", var_name, var_representation); + else + s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); + } + else + s.Printf ("%s=", var_name); + } + + if (close_paren) + s.PutCString (close_paren); + else + s.PutChar(')'); + + } + else + { + s.PutCString(cstr); + } + return true; + } + } + else if (sc->symbol) + { + const char *cstr = sc->symbol->GetName().AsCString (NULL); + if (cstr) + { + s.PutCString(cstr); + return true; + } + } + } + return false; + + case Entry::Type::FunctionAddrOffset: + if (addr) + { + if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, false, false)) + return true; + } + return false; + + case Entry::Type::FunctionAddrOffsetConcrete: + if (addr) + { + if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, true, true)) + return true; + } + return false; + + case Entry::Type::FunctionLineOffset: + if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false)) + return true; + return false; + + case Entry::Type::FunctionPCOffset: + if (exe_ctx) + { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + { + if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, frame->GetFrameCodeAddress(), false, false)) + return true; + } + } + return false; + + case Entry::Type::LineEntryFile: + if (sc && sc->line_entry.IsValid()) + { + Module *module = sc->module_sp.get(); + if (module) + { + if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) + return true; + } + } + return false; + + case Entry::Type::LineEntryLineNumber: + if (sc && sc->line_entry.IsValid()) + { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, sc->line_entry.line); + return true; + } + return false; + + case Entry::Type::LineEntryStartAddress: + case Entry::Type::LineEntryEndAddress: + if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) + { + Address addr = sc->line_entry.range.GetBaseAddress(); + + if (entry.type == Entry::Type::LineEntryEndAddress) + addr.Slide(sc->line_entry.range.GetByteSize()); + if (DumpAddress(s, sc, exe_ctx, addr, false)) + return true; + } + return false; + + case Entry::Type::CurrentPCArrow: + if (addr && exe_ctx && exe_ctx->GetFramePtr()) + { + RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); + if (reg_ctx.get()) + { + addr_t pc_loadaddr = reg_ctx->GetPC(); + if (pc_loadaddr != LLDB_INVALID_ADDRESS) + { + Address pc; + pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); + if (pc == *addr) + { + s.Printf ("-> "); + return true; + } + } + } + s.Printf(" "); + return true; + } + return false; + } + return false; +} + +static bool +DumpCommaSeparatedChildEntryNames (Stream &s, const FormatEntity::Entry::Definition *parent) +{ + if (parent->children) + { + const size_t n = parent->num_children; + for (size_t i=0; i 0) + s.PutCString(", "); + s.Printf ("\"%s\"", parent->children[i].name); + } + return true; + } + return false; +} + + +static Error +ParseEntry (const llvm::StringRef &format_str, + const FormatEntity::Entry::Definition *parent, + FormatEntity::Entry &entry) +{ + Error error; + + const size_t sep_pos = format_str.find_first_of(".[:"); + const char sep_char = (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; + llvm::StringRef key = format_str.substr(0, sep_pos); + + const size_t n = parent->num_children; + for (size_t i=0; ichildren + i; + if (key.equals(entry_def->name) || entry_def->name[0] == '*') + { + llvm::StringRef value; + if (sep_char) + value = format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); + switch (entry_def->type) + { + case FormatEntity::Entry::Type::ParentString: + entry.string = std::move(format_str.str()); + return error; // Success + + case FormatEntity::Entry::Type::ParentNumber: + entry.number = entry_def->data; + return error; // Success + + case FormatEntity::Entry::Type::InsertString: + entry.type = entry_def->type; + entry.string = entry_def->string; + return error; // Success + + default: + entry.type = entry_def->type; + break; + } + + if (value.empty()) + { + if (entry_def->type == FormatEntity::Entry::Type::Invalid) + { + if (entry_def->children) + { + StreamString error_strm; + error_strm.Printf("'%s' can't be specified on its own, you must access one of its children: ", entry_def->name); + DumpCommaSeparatedChildEntryNames (error_strm, entry_def); + error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); + } + else if (sep_char == ':') + { + // Any value whose separator is a with a ':' means this value has a string argument + // that needs to be stored in the entry (like "${script.var:}"). + // In this case the string value is the empty string which is ok. + } + else + { + error.SetErrorStringWithFormat("%s", "invalid entry definitions"); + } + } + } + else + { + if (entry_def->children) + { + error = ParseEntry (value, entry_def, entry); + } + else if (sep_char == ':') + { + // Any value whose separator is a with a ':' means this value has a string argument + // that needs to be stored in the entry (like "${script.var:modulename.function}") + entry.string = std::move(value.str()); + } + else + { + error.SetErrorStringWithFormat("'%s' followed by '%s' but it has no children", + key.str().c_str(), + value.str().c_str()); + } + } + return error; + } + } + StreamString error_strm; + if (parent->type == FormatEntity::Entry::Type::Root) + error_strm.Printf("invalid top level item '%s'. Valid top level items are: ", key.str().c_str()); + else + error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", key.str().c_str(), parent->name); + DumpCommaSeparatedChildEntryNames (error_strm, parent); + error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); + return error; +} + + +static const FormatEntity::Entry::Definition * +FindEntry (const llvm::StringRef &format_str, const FormatEntity::Entry::Definition *parent, llvm::StringRef &remainder) +{ + Error error; + + std::pair p = format_str.split('.'); + const size_t n = parent->num_children; + for (size_t i=0; ichildren + i; + if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') + { + if (p.second.empty()) + { + if (format_str.back() == '.') + remainder = format_str.drop_front(format_str.size() - 1); + else + remainder = llvm::StringRef(); // Exact match + return entry_def; + } + else + { + if (entry_def->children) + { + return FindEntry (p.second, entry_def, remainder); + } + else + { + remainder = p.second; + return entry_def; + } + } + } + } + remainder = format_str; + return parent; +} + +Error +FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth) +{ + Error error; + while (!format.empty() && error.Success()) + { + const size_t non_special_chars = format.find_first_of("${}\\"); + + if (non_special_chars == llvm::StringRef::npos) + { + // No special characters, just string bytes so add them and we are done + parent_entry.AppendText(format); + return error; + } + + if (non_special_chars > 0) + { + // We have a special character, so add all characters before these as a plain string + parent_entry.AppendText(format.substr(0,non_special_chars)); + format = format.drop_front(non_special_chars); + } + + switch (format[0]) + { + case '\0': + return error; + + case '{': + { + format = format.drop_front(); // Skip the '{' + Entry scope_entry(Entry::Type::Scope); + error = FormatEntity::ParseInternal (format, scope_entry, depth+1); + if (error.Fail()) + return error; + parent_entry.AppendEntry(std::move(scope_entry)); + } + break; + + case '}': + if (depth == 0) + error.SetErrorString("unmatched '}' character"); + else + format = format.drop_front(); // Skip the '}' as we are at the end of the scope + return error; + + case '\\': + { + format = format.drop_front(); // Skip the '\' character + if (format.empty()) + { + error.SetErrorString("'\\' character was not followed by another character"); + return error; + } + + const char desens_char = format[0]; + format = format.drop_front(); // Skip the desensitized char character + switch (desens_char) + { + case 'a': parent_entry.AppendChar('\a'); break; + case 'b': parent_entry.AppendChar('\b'); break; + case 'f': parent_entry.AppendChar('\f'); break; + case 'n': parent_entry.AppendChar('\n'); break; + case 'r': parent_entry.AppendChar('\r'); break; + case 't': parent_entry.AppendChar('\t'); break; + case 'v': parent_entry.AppendChar('\v'); break; + case '\'': parent_entry.AppendChar('\''); break; + case '\\': parent_entry.AppendChar('\\'); break; + case '0': + // 1 to 3 octal chars + { + // Make a string that can hold onto the initial zero char, + // up to 3 octal digits, and a terminating NULL. + char oct_str[5] = { 0, 0, 0, 0, 0 }; + + int i; + for (i=0; (format[i] >= '0' && format[i] <= '7') && i<4; ++i) + oct_str[i] = format[i]; + + // We don't want to consume the last octal character since + // the main for loop will do this for us, so we advance p by + // one less than i (even if i is zero) + format = format.drop_front(i); + unsigned long octal_value = ::strtoul (oct_str, NULL, 8); + if (octal_value <= UINT8_MAX) + { + parent_entry.AppendChar((char)octal_value); + } + else + { + error.SetErrorString("octal number is larger than a single byte"); + return error; + } + } + break; + + case 'x': + // hex number in the format + if (isxdigit(format[0])) + { + // Make a string that can hold onto two hex chars plus a + // NULL terminator + char hex_str[3] = { 0,0,0 }; + hex_str[0] = format[0]; + + format = format.drop_front(); + + if (isxdigit(format[0])) + { + hex_str[1] = format[0]; + format = format.drop_front(); + } + + unsigned long hex_value = strtoul (hex_str, NULL, 16); + if (hex_value <= UINT8_MAX) + { + parent_entry.AppendChar((char)hex_value); + } + else + { + error.SetErrorString("hex number is larger than a single byte"); + return error; + } + } + else + { + parent_entry.AppendChar(desens_char); + } + break; + + default: + // Just desensitize any other character by just printing what + // came after the '\' + parent_entry.AppendChar(desens_char); + break; + } + } + break; + + case '$': + if (format.size() == 1) + { + // '$' at the end of a format string, just print the '$' + parent_entry.AppendText("$"); + } + else + { + format = format.drop_front(); // Skip the '$' + + if (format[0] == '{') + { + format = format.drop_front(); // Skip the '{' + + llvm::StringRef variable, variable_format; + error = FormatEntity::ExtractVariableInfo (format, variable, variable_format); + if (error.Fail()) + return error; + bool verify_is_thread_id = false; + Entry entry; + if (!variable_format.empty()) + { + entry.printf_format = std::move(variable_format.str()); + + // If the format contains a '%' we are going to assume this is + // a printf style format. So if you want to format your thread ID + // using "0x%llx" you can use: + // ${thread.id%0x%llx} + // + // If there is no '%' in the format, then it is assumed to be a + // LLDB format name, or one of the extended formats specified in + // the switch statement below. + + if (entry.printf_format.find('%') == std::string::npos) + { + bool clear_printf = false; + + if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(), + false, + entry.fmt)) + { + // We have an LLDB format, so clear the printf format + clear_printf = true; + } + else if (entry.printf_format.size() == 1) + { + switch (entry.printf_format[0]) + { + case '@': // if this is an @ sign, print ObjC description + entry.number = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; + clear_printf = true; + break; + case 'V': // if this is a V, print the value using the default format + entry.number = ValueObject::eValueObjectRepresentationStyleValue; + clear_printf = true; + break; + case 'L': // if this is an L, print the location of the value + entry.number = ValueObject::eValueObjectRepresentationStyleLocation; + clear_printf = true; + break; + case 'S': // if this is an S, print the summary after all + entry.number = ValueObject::eValueObjectRepresentationStyleSummary; + clear_printf = true; + break; + case '#': // if this is a '#', print the number of children + entry.number = ValueObject::eValueObjectRepresentationStyleChildrenCount; + clear_printf = true; + break; + case 'T': // if this is a 'T', print the type + entry.number = ValueObject::eValueObjectRepresentationStyleType; + clear_printf = true; + break; + case 'N': // if this is a 'N', print the name + entry.number = ValueObject::eValueObjectRepresentationStyleName; + clear_printf = true; + break; + case '>': // if this is a '>', print the expression path + entry.number = ValueObject::eValueObjectRepresentationStyleExpressionPath; + clear_printf = true; + break; + default: + error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str()); + return error; + } + } + else if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(), + true, + entry.fmt)) + { + clear_printf = true; + } + else if (entry.printf_format == "tid") + { + verify_is_thread_id = true; + } + else + { + error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str()); + return error; + } + + // Our format string turned out to not be a printf style format + // so lets clear the string + if (clear_printf) + entry.printf_format.clear(); + } + } + + // Check for dereferences + if (variable[0] == '*') + { + entry.deref = true; + variable = variable.drop_front(); + } + + error = ParseEntry (variable, &g_root, entry); + if (error.Fail()) + return error; + + if (verify_is_thread_id) + { + if (entry.type != Entry::Type::ThreadID && + entry.type != Entry::Type::ThreadProtocolID) + { + error.SetErrorString("the 'tid' format can only be used on ${thread.id} and ${thread.protocol_id}"); + } + } + + switch (entry.type) + { + case Entry::Type::Variable: + case Entry::Type::VariableSynthetic: + if (entry.number == 0) + { + if (entry.string.empty()) + entry.number = ValueObject::eValueObjectRepresentationStyleValue; + else + entry.number = ValueObject::eValueObjectRepresentationStyleSummary; + } + break; + default: + // Make sure someone didn't try to dereference anything but ${var} or ${svar} + if (entry.deref) + { + error.SetErrorStringWithFormat("${%s} can't be dereferenced, only ${var} and ${svar} can.", variable.str().c_str()); + return error; + } + } + // Check if this entry just wants to insert a constant string + // value into the parent_entry, if so, insert the string with + // AppendText, else append the entry to the parent_entry. + if (entry.type == Entry::Type::InsertString) + parent_entry.AppendText(entry.string.c_str()); + else + parent_entry.AppendEntry(std::move(entry)); + } + } + break; + } + } + return error; +} + + +Error +FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format) +{ + Error error; + variable_name = llvm::StringRef(); + variable_format = llvm::StringRef(); + + const size_t paren_pos = format_str.find_first_of('}'); + if (paren_pos != llvm::StringRef::npos) + { + const size_t percent_pos = format_str.find_first_of('%'); + if (percent_pos < paren_pos) + { + if (percent_pos > 0) + { + if (percent_pos > 1) + variable_name = format_str.substr(0, percent_pos); + variable_format = format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); + } + } + else + { + variable_name = format_str.substr(0, paren_pos); + } + // Strip off elements and the formatting and the trailing '}' + format_str = format_str.substr(paren_pos + 1); + } + else + { + error.SetErrorStringWithFormat("missing terminating '}' character for '${%s'", format_str.str().c_str()); + } + return error; +} + +bool +FormatEntity::FormatFileSpec (const FileSpec &file_spec, Stream &s, llvm::StringRef variable_name, llvm::StringRef variable_format) +{ + if (variable_name.empty() || variable_name.equals(".fullpath")) + { + file_spec.Dump(&s); + return true; + } + else if (variable_name.equals(".basename")) + { + s.PutCString(file_spec.GetFilename().AsCString("")); + return true; + } + else if (variable_name.equals(".dirname")) + { + s.PutCString(file_spec.GetFilename().AsCString("")); + return true; + } + return false; +} + +static std::string +MakeMatch (const llvm::StringRef &prefix, const char *suffix) +{ + std::string match(prefix.str()); + match.append(suffix); + return std::move(match); +} + +static void +AddMatches (const FormatEntity::Entry::Definition *def, + const llvm::StringRef &prefix, + const llvm::StringRef &match_prefix, + StringList &matches) +{ + const size_t n = def->num_children; + if (n > 0) + { + for (size_t i=0; ichildren[i].name)); + else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0) + matches.AppendString(MakeMatch (prefix, def->children[i].name + match_prefix.size())); + } + } +} +size_t +FormatEntity::AutoComplete (const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) +{ + word_complete = false; + llvm::StringRef str(s + match_start_point); + matches.Clear(); + + const size_t dollar_pos = str.rfind('$'); + if (dollar_pos != llvm::StringRef::npos) + { + // Hitting TAB after $ at the end of the string add a "{" + if (dollar_pos == str.size() - 1) + { + std::string match = std::move(str.str()); + match.append("{"); + matches.AppendString(std::move(match)); + } + else if (str[dollar_pos + 1] == '{') + { + const size_t close_pos = str.find('}', dollar_pos + 2); + if (close_pos == llvm::StringRef::npos) + { + const size_t format_pos = str.find('%', dollar_pos + 2); + if (format_pos == llvm::StringRef::npos) + { + llvm::StringRef partial_variable (str.substr(dollar_pos + 2)); + if (partial_variable.empty()) + { + // Suggest all top level entites as we are just past "${" + AddMatches(&g_root, str, llvm::StringRef(), matches); + } + else + { + // We have a partially specified variable, find it + llvm::StringRef remainder; + const FormatEntity::Entry::Definition* entry_def = FindEntry (partial_variable, &g_root, remainder); + if (entry_def) + { + const size_t n = entry_def->num_children; + + if (remainder.empty()) + { + // Exact match + if (n > 0) + { + // "${thread.info" + matches.AppendString(std::move(MakeMatch (str, "."))); + } + else + { + // "${thread.id" + matches.AppendString(std::move(MakeMatch (str, "}"))); + word_complete = true; + } + } + else if (remainder.equals(".")) + { + // "${thread." + AddMatches(entry_def, str, llvm::StringRef(), matches); + } + else + { + // We have a partial match + // "${thre" + AddMatches(entry_def, str, remainder, matches); + } + } + } + } + } + } + } + return matches.GetSize(); +} diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index 21ba965ba212..747fd4411d4d 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -3217,6 +3217,8 @@ class FrameTreeDelegate : public TreeDelegate FrameTreeDelegate () : TreeDelegate() { + FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}", + m_format); } virtual ~FrameTreeDelegate() @@ -3236,9 +3238,7 @@ class FrameTreeDelegate : public TreeDelegate StreamString strm; const SymbolContext &sc = frame_sp->GetSymbolContext(eSymbolContextEverything); ExecutionContext exe_ctx (frame_sp); - //const char *frame_format = "frame #${frame.index}: ${module.file.basename}{`${function.name}${function.pc-offset}}}"; - const char *frame_format = "frame #${frame.index}: {${function.name}${function.pc-offset}}}"; - if (Debugger::FormatPrompt (frame_format, &sc, &exe_ctx, NULL, strm)) + if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, NULL, NULL, false, false)) { int right_pad = 1; window.PutCStringTruncated(strm.GetString().c_str(), right_pad); @@ -3265,6 +3265,8 @@ class FrameTreeDelegate : public TreeDelegate } return false; } +protected: + FormatEntity::Entry m_format; }; class ThreadTreeDelegate : public TreeDelegate @@ -3276,6 +3278,8 @@ class ThreadTreeDelegate : public TreeDelegate m_tid (LLDB_INVALID_THREAD_ID), m_stop_id (UINT32_MAX) { + FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}", + m_format); } virtual @@ -3306,8 +3310,7 @@ class ThreadTreeDelegate : public TreeDelegate { StreamString strm; ExecutionContext exe_ctx (thread_sp); - const char *format = "thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}"; - if (Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm)) + if (FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false)) { int right_pad = 1; window.PutCStringTruncated(strm.GetString().c_str(), right_pad); @@ -3383,6 +3386,8 @@ class ThreadTreeDelegate : public TreeDelegate std::shared_ptr m_frame_delegate_sp; lldb::user_id_t m_tid; uint32_t m_stop_id; + FormatEntity::Entry m_format; + }; class ThreadsTreeDelegate : public TreeDelegate @@ -3394,6 +3399,8 @@ class ThreadsTreeDelegate : public TreeDelegate m_debugger (debugger), m_stop_id (UINT32_MAX) { + FormatEntity::Parse("process ${process.id}{, name = ${process.name}}", + m_format); } virtual @@ -3415,8 +3422,7 @@ class ThreadsTreeDelegate : public TreeDelegate { StreamString strm; ExecutionContext exe_ctx (process_sp); - const char *format = "process ${process.id}{, name = ${process.name}}"; - if (Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm)) + if (FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false)) { int right_pad = 1; window.PutCStringTruncated(strm.GetString().c_str(), right_pad); @@ -3472,6 +3478,8 @@ class ThreadsTreeDelegate : public TreeDelegate std::shared_ptr m_thread_delegate_sp; Debugger &m_debugger; uint32_t m_stop_id; + FormatEntity::Entry m_format; + }; class ValueObjectListDelegate : public WindowDelegate @@ -4635,6 +4643,8 @@ class StatusBarWindowDelegate : public WindowDelegate StatusBarWindowDelegate (Debugger &debugger) : m_debugger (debugger) { + FormatEntity::Parse("Thread: ${thread.id%tid}", + m_format); } virtual @@ -4659,8 +4669,7 @@ class StatusBarWindowDelegate : public WindowDelegate if (StateIsStoppedState(state, true)) { StreamString strm; - const char *format = "Thread: ${thread.id%tid}"; - if (thread && Debugger::FormatPrompt (format, NULL, &exe_ctx, NULL, strm)) + if (thread && FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false)) { window.MoveCursor (40, 0); window.PutCStringTruncated(strm.GetString().c_str(), 1); @@ -4686,6 +4695,7 @@ class StatusBarWindowDelegate : public WindowDelegate protected: Debugger &m_debugger; + FormatEntity::Entry m_format; }; class SourceFileWindowDelegate : public WindowDelegate diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp index d205d363b764..fe4cfb366c88 100644 --- a/source/Core/Log.cpp +++ b/source/Core/Log.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C Includes #include #include @@ -20,7 +18,6 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" @@ -219,7 +216,6 @@ Log::LogIf (uint32_t bits, const char *format, ...) } } - //---------------------------------------------------------------------- // Printing of errors that are not fatal. //---------------------------------------------------------------------- diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp index c0ab66cd2880..e1598d30e4e5 100644 --- a/source/Core/Mangled.cpp +++ b/source/Core/Mangled.cpp @@ -10,8 +10,9 @@ // FreeBSD9-STABLE requires this to know about size_t in cxxabi.h #include -#if defined(_MSC_VER) -// Cannot enable the builtin demangler on msvc as it does not support the cpp11 within the implementation. +#if defined(_MSC_VER) +#include "lldb/Host/windows/windows.h" +#include #elif defined (__FreeBSD__) #define LLDB_USE_BUILTIN_DEMANGLER #else @@ -4998,7 +4999,11 @@ static inline bool cstring_is_mangled (const char *s) { if (s) - return s[0] == '_' && s[1] == 'Z'; +#if defined(_MSC_VER) + return (s[0] == '?'); +#else + return (s[0] == '_' && s[1] == 'Z'); +#endif return false; } @@ -5226,15 +5231,27 @@ Mangled::GetDemangledName () const if (!demangled_name) demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL); #elif defined(_MSC_VER) - // Cannot demangle on msvc. - char *demangled_name = nullptr; + char *demangled_name = (char *)::malloc(1024); + ::ZeroMemory(demangled_name, 1024); + DWORD result = ::UnDecorateSymbolName(mangled_cstr, demangled_name, 1023, + UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected keywords + UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords + UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications + UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers + UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords + ); + if (result == 0) + { + free (demangled_name); + demangled_name = nullptr; + } #else char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL); #endif if (demangled_name) { - m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); + m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); free (demangled_name); } } @@ -5335,6 +5352,21 @@ Mangled::MemorySize () const return m_mangled.MemorySize() + m_demangled.MemorySize(); } +lldb::LanguageType +Mangled::GetLanguage () +{ + ConstString mangled = GetMangledName(); + if (mangled) + { + if (GetDemangledName()) + { + if (cstring_is_mangled(mangled.GetCString())) + return lldb::eLanguageTypeC_plus_plus; + } + } + return lldb::eLanguageTypeUnknown; +} + //---------------------------------------------------------------------- // Dump OBJ to the supplied stream S. //---------------------------------------------------------------------- diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index 900eea2e0419..891bd87a20d4 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -152,7 +152,6 @@ Module::Module (const ModuleSpec &module_spec) : m_did_load_symbol_vendor (false), m_did_parse_uuid (false), m_did_init_ast (false), - m_is_dynamic_loader_module (false), m_file_has_changed (false), m_first_file_changed_log (false) { @@ -257,7 +256,6 @@ Module::Module(const FileSpec& file_spec, m_did_load_symbol_vendor (false), m_did_parse_uuid (false), m_did_init_ast (false), - m_is_dynamic_loader_module (false), m_file_has_changed (false), m_first_file_changed_log (false) { @@ -304,7 +302,6 @@ Module::Module () : m_did_load_symbol_vendor (false), m_did_parse_uuid (false), m_did_init_ast (false), - m_is_dynamic_loader_module (false), m_file_has_changed (false), m_first_file_changed_log (false) { @@ -1304,10 +1301,14 @@ Module::GetObjectFile() data_offset); if (m_objfile_sp) { - // Once we get the object file, update our module with the object file's + // Once we get the object file, update our module with the object file's // architecture since it might differ in vendor/os if some parts were - // unknown. - m_objfile_sp->GetArchitecture (m_arch); + // unknown. But since the matching arch might already be more specific + // than the generic COFF architecture, only merge in those values that + // overwrite unspecified unknown values. + ArchSpec new_arch; + m_objfile_sp->GetArchitecture(new_arch); + m_arch.MergeFrom(new_arch); } else { @@ -1732,7 +1733,7 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, if (CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename)) lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); else - lookup_name_type_mask = eFunctionNameTypeFull; + lookup_name_type_mask |= eFunctionNameTypeFull; } else { @@ -1821,3 +1822,13 @@ Module::CreateJITModule (const lldb::ObjectFileJITDelegateSP &delegate_sp) return ModuleSP(); } +bool +Module::GetIsDynamicLinkEditor() +{ + ObjectFile * obj_file = GetObjectFile (); + + if (obj_file) + return obj_file->GetIsDynamicLinkEditor(); + + return false; +} diff --git a/source/Core/RegisterValue.cpp b/source/Core/RegisterValue.cpp index 91f5bea805c6..272c1eecf920 100644 --- a/source/Core/RegisterValue.cpp +++ b/source/Core/RegisterValue.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" #include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" using namespace lldb; using namespace lldb_private; @@ -467,7 +468,7 @@ RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *va case eEncodingUint: if (byte_size <= sizeof (uint64_t)) { - uint64_t uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); + uint64_t uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string value", value_str); else if (!Args::UInt64ValueIsValidForByteSize (uval64, byte_size)) @@ -488,7 +489,7 @@ RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *va case eEncodingSint: if (byte_size <= sizeof (long long)) { - uint64_t sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); + uint64_t sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat ("'%s' is not a valid signed integer string value", value_str); else if (!Args::SInt64ValueIsValidForByteSize (sval64, byte_size)) diff --git a/source/Core/RegularExpression.cpp b/source/Core/RegularExpression.cpp index 54924d069537..3f712e1b2daa 100644 --- a/source/Core/RegularExpression.cpp +++ b/source/Core/RegularExpression.cpp @@ -7,9 +7,22 @@ // //===----------------------------------------------------------------------===// +#include #include "lldb/Core/RegularExpression.h" #include "llvm/ADT/StringRef.h" -#include +#include "lldb/Core/Error.h" + + +//---------------------------------------------------------------------- +// Enable enhanced mode if it is available. This allows for things like +// \d for digit, \s for space, and many more, but it isn't available +// everywhere. +//---------------------------------------------------------------------- +#if defined(REG_ENHANCED) +#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED|REG_EXTENDED) +#else +#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED) +#endif using namespace lldb_private; @@ -19,26 +32,11 @@ using namespace lldb_private; RegularExpression::RegularExpression() : m_re(), m_comp_err (1), - m_preg(), - m_compile_flags(REG_EXTENDED) + m_preg() { memset(&m_preg,0,sizeof(m_preg)); } -//---------------------------------------------------------------------- -// Constructor that compiles "re" using "flags" and stores the -// resulting compiled regular expression into this object. -//---------------------------------------------------------------------- -RegularExpression::RegularExpression(const char* re, int flags) : - m_re(), - m_comp_err (1), - m_preg(), - m_compile_flags(flags) -{ - memset(&m_preg,0,sizeof(m_preg)); - Compile(re); -} - //---------------------------------------------------------------------- // Constructor that compiles "re" using "flags" and stores the // resulting compiled regular expression into this object. @@ -46,8 +44,7 @@ RegularExpression::RegularExpression(const char* re, int flags) : RegularExpression::RegularExpression(const char* re) : m_re(), m_comp_err (1), - m_preg(), - m_compile_flags(REG_EXTENDED) + m_preg() { memset(&m_preg,0,sizeof(m_preg)); Compile(re); @@ -56,16 +53,14 @@ RegularExpression::RegularExpression(const char* re) : RegularExpression::RegularExpression(const RegularExpression &rhs) { memset(&m_preg,0,sizeof(m_preg)); - Compile(rhs.GetText(), rhs.GetCompileFlags()); + Compile(rhs.GetText()); } const RegularExpression & RegularExpression::operator= (const RegularExpression &rhs) { if (&rhs != this) - { - Compile (rhs.GetText(), rhs.GetCompileFlags()); - } + Compile (rhs.GetText()); return *this; } //---------------------------------------------------------------------- @@ -93,20 +88,13 @@ RegularExpression::~RegularExpression() //---------------------------------------------------------------------- bool RegularExpression::Compile(const char* re) -{ - return Compile (re, m_compile_flags); -} - -bool -RegularExpression::Compile(const char* re, int flags) { Free(); - m_compile_flags = flags; if (re && re[0]) { m_re = re; - m_comp_err = ::regcomp (&m_preg, re, flags); + m_comp_err = ::regcomp (&m_preg, re, DEFAULT_COMPILE_FLAGS); } else { @@ -126,7 +114,7 @@ RegularExpression::Compile(const char* re, int flags) // will be executed using the "execute_flags". //--------------------------------------------------------------------- bool -RegularExpression::Execute(const char* s, Match *match, int execute_flags) const +RegularExpression::Execute (const char* s, Match *match) const { int err = 1; if (s != NULL && m_comp_err == 0) @@ -137,7 +125,7 @@ RegularExpression::Execute(const char* s, Match *match, int execute_flags) const s, match->GetSize(), match->GetData(), - execute_flags); + 0); } else { @@ -145,7 +133,7 @@ RegularExpression::Execute(const char* s, Match *match, int execute_flags) const s, 0, NULL, - execute_flags); + 0); } } diff --git a/source/Core/Scalar.cpp b/source/Core/Scalar.cpp index 1bfe6f2f1baf..0e9b98dc4ab6 100644 --- a/source/Core/Scalar.cpp +++ b/source/Core/Scalar.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Host/Endian.h" +#include "lldb/Host/StringConvert.h" #include "Plugins/Process/Utility/InstructionUtils.h" @@ -1790,7 +1791,7 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by case eEncodingUint: if (byte_size <= sizeof (unsigned long long)) { - uint64_t uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success); + uint64_t uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string value", value_str); else if (!UIntValueIsValidForSize (uval64, byte_size)) @@ -1819,7 +1820,7 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by case eEncodingSint: if (byte_size <= sizeof (long long)) { - uint64_t sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success); + uint64_t sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat ("'%s' is not a valid signed integer string value", value_str); else if (!SIntValueIsValidForSize (sval64, byte_size)) diff --git a/source/Core/StreamFile.cpp b/source/Core/StreamFile.cpp index 2285ca954457..9f8dd629e3d4 100644 --- a/source/Core/StreamFile.cpp +++ b/source/Core/StreamFile.cpp @@ -49,7 +49,8 @@ StreamFile::StreamFile (FILE *fh, bool transfer_ownership) : StreamFile::StreamFile (const char *path) : Stream (), - m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate, lldb::eFilePermissionsFileDefault) + m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec, + lldb::eFilePermissionsFileDefault) { } diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp index db33fce4a03e..a416d0745a69 100644 --- a/source/Core/Value.cpp +++ b/source/Core/Value.cpp @@ -277,7 +277,7 @@ Value::GetValueByteSize (Error *error_ptr) { const ClangASTType &ast_type = GetClangType(); if (ast_type.IsValid()) - byte_size = ast_type.GetByteSize(); + byte_size = ast_type.GetByteSize(nullptr); } break; } @@ -434,7 +434,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count); if (type_encoding == eEncodingUint || type_encoding == eEncodingSint) - limit_byte_size = ast_type.GetByteSize(); + limit_byte_size = ast_type.GetByteSize(nullptr); } if (m_value.GetData (data, limit_byte_size)) diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp index fa5fb14db05b..b72e5c3f18c6 100644 --- a/source/Core/ValueObject.cpp +++ b/source/Core/ValueObject.cpp @@ -99,6 +99,7 @@ ValueObject::ValueObject (ValueObject &parent) : m_user_id_of_forced_summary(), m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid), m_value_checksum(), + m_preferred_display_language(lldb::eLanguageTypeUnknown), m_value_is_valid (false), m_value_did_change (false), m_children_count_valid (false), @@ -149,6 +150,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope, m_user_id_of_forced_summary(), m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), m_value_checksum(), + m_preferred_display_language(lldb::eLanguageTypeUnknown), m_value_is_valid (false), m_value_did_change (false), m_children_count_valid (false), @@ -969,7 +971,9 @@ ValueObject::GetPointeeData (DataExtractor& data, if (item_count == 0) return 0; - const uint64_t item_type_size = pointee_or_element_clang_type.GetByteSize(); + ExecutionContext exe_ctx (GetExecutionContextRef()); + + const uint64_t item_type_size = pointee_or_element_clang_type.GetByteSize(&exe_ctx); const uint64_t bytes = item_count * item_type_size; const uint64_t offset = item_idx * item_type_size; @@ -1045,7 +1049,7 @@ ValueObject::GetPointeeData (DataExtractor& data, break; case eAddressTypeHost: { - const uint64_t max_bytes = GetClangType().GetByteSize(); + const uint64_t max_bytes = GetClangType().GetByteSize(&exe_ctx); if (max_bytes > offset) { size_t bytes_read = std::min(max_bytes - offset, bytes); @@ -1505,14 +1509,14 @@ ValueObject::GetValueAsSigned (int64_t fail_value, bool *success) { if (success) *success = true; - return scalar.SLongLong(fail_value); + return scalar.SLongLong(fail_value); } // fallthrough, otherwise... } if (success) *success = false; - return fail_value; + return fail_value; } // if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep @@ -2220,10 +2224,12 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type if (!can_create) return ValueObjectSP(); + ExecutionContext exe_ctx (GetExecutionContextRef()); + ValueObjectChild *synthetic_child = new ValueObjectChild(*this, type, name_const_str, - type.GetByteSize(), + type.GetByteSize(&exe_ctx), offset, 0, 0, @@ -2261,10 +2267,12 @@ ValueObject::GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool c const bool is_base_class = true; + ExecutionContext exe_ctx (GetExecutionContextRef()); + ValueObjectChild *synthetic_child = new ValueObjectChild(*this, type, name_const_str, - type.GetByteSize(), + type.GetByteSize(&exe_ctx), offset, 0, 0, @@ -4128,16 +4136,22 @@ ValueObject::GetRoot () { if (m_root) return m_root; - ValueObject* parent = m_parent; - if (!parent) - return (m_root = this); - while (parent->m_parent) + return (m_root = FollowParentChain( [] (ValueObject* vo) -> bool { + return (vo->m_parent != nullptr); + })); +} + +ValueObject* +ValueObject::FollowParentChain (std::function f) +{ + ValueObject* vo = this; + while (vo) { - if (parent->m_root) - return (m_root = parent->m_root); - parent = parent->m_parent; + if (f(vo) == false) + break; + vo = vo->m_parent; } - return (m_root = parent); + return vo; } AddressType @@ -4181,24 +4195,33 @@ ValueObject::GetFormat () const lldb::LanguageType ValueObject::GetPreferredDisplayLanguage () { - lldb::LanguageType type = lldb::eLanguageTypeUnknown; - if (GetRoot()) + lldb::LanguageType type = m_preferred_display_language; + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { - if (GetRoot() == this) + if (GetRoot()) { - if (StackFrameSP frame_sp = GetFrameSP()) + if (GetRoot() == this) { - const SymbolContext& sc(frame_sp->GetSymbolContext(eSymbolContextCompUnit)); - if (CompileUnit* cu = sc.comp_unit) - type = cu->GetLanguage(); + if (StackFrameSP frame_sp = GetFrameSP()) + { + const SymbolContext& sc(frame_sp->GetSymbolContext(eSymbolContextCompUnit)); + if (CompileUnit* cu = sc.comp_unit) + type = cu->GetLanguage(); + } + } + else + { + type = GetRoot()->GetPreferredDisplayLanguage(); } } - else - { - type = GetRoot()->GetPreferredDisplayLanguage(); - } } - return type; + return (m_preferred_display_language = type); // only compute it once +} + +void +ValueObject::SetPreferredDisplayLanguage (lldb::LanguageType lt) +{ + m_preferred_display_language = lt; } bool diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp index fc870d726221..e8b477a74a52 100644 --- a/source/Core/ValueObjectConstResult.cpp +++ b/source/Core/ValueObjectConstResult.cpp @@ -256,8 +256,10 @@ ValueObjectConstResult::GetValueType() const uint64_t ValueObjectConstResult::GetByteSize() { + ExecutionContext exe_ctx(GetExecutionContextRef()); + if (m_byte_size == 0) - m_byte_size = GetClangType().GetByteSize(); + SetByteSize(GetClangType().GetByteSize(&exe_ctx)); return m_byte_size; } diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp index 1b8ec8083f8f..89b98a1db1ba 100644 --- a/source/Core/ValueObjectDynamicValue.cpp +++ b/source/Core/ValueObjectDynamicValue.cpp @@ -127,7 +127,7 @@ ValueObjectDynamicValue::GetByteSize() { const bool success = UpdateValueIfNeeded(false); if (success && m_dynamic_type_info.HasType()) - return m_value.GetValueByteSize(NULL); + return m_value.GetValueByteSize(nullptr); else return m_parent->GetByteSize(); } diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp index 5fbe87b66522..9f1953138f62 100644 --- a/source/Core/ValueObjectMemory.cpp +++ b/source/Core/ValueObjectMemory.cpp @@ -169,7 +169,7 @@ ValueObjectMemory::GetByteSize() { if (m_type_sp) return m_type_sp->GetByteSize(); - return m_clang_type.GetByteSize (); + return m_clang_type.GetByteSize (nullptr); } lldb::ValueType diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp index dafe73a5e57e..e266267981b8 100644 --- a/source/Core/ValueObjectSyntheticFilter.cpp +++ b/source/Core/ValueObjectSyntheticFilter.cpp @@ -298,3 +298,9 @@ ValueObjectSynthetic::CanProvideValue () return true; return m_parent->CanProvideValue(); } + +bool +ValueObjectSynthetic::SetValueFromCString (const char *value_str, Error& error) +{ + return m_parent->SetValueFromCString(value_str, error); +} diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp index ab74a50e7cd5..ed2aeb3d9634 100644 --- a/source/Core/ValueObjectVariable.cpp +++ b/source/Core/ValueObjectVariable.cpp @@ -105,12 +105,14 @@ ValueObjectVariable::CalculateNumChildren() uint64_t ValueObjectVariable::GetByteSize() { + ExecutionContext exe_ctx(GetExecutionContextRef()); + ClangASTType type(GetClangType()); if (!type.IsValid()) return 0; - return type.GetByteSize(); + return type.GetByteSize(&exe_ctx); } lldb::ValueType diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp index 04cdadf5a98f..5aa8289794c1 100644 --- a/source/DataFormatters/CXXFormatterFunctions.cpp +++ b/source/DataFormatters/CXXFormatterFunctions.cpp @@ -317,7 +317,7 @@ lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Strea return false; ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); - const uint32_t wchar_size = wchar_clang_type.GetBitSize(); + const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(data_addr); diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp index 01799cef5e4e..ae52b3309ed8 100644 --- a/source/DataFormatters/FormatManager.cpp +++ b/source/DataFormatters/FormatManager.cpp @@ -251,6 +251,8 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, do { lldb::ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + break; ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime(); if (runtime == nullptr) break; diff --git a/source/DataFormatters/LibCxx.cpp b/source/DataFormatters/LibCxx.cpp index 26bbcf91242f..728ad84341f0 100644 --- a/source/DataFormatters/LibCxx.cpp +++ b/source/DataFormatters/LibCxx.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/Stream.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -139,7 +140,7 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (si return ValueObjectSP(); } bool bit_set = ((byte & mask) != 0); - DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(),0)); + DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),0)); if (bit_set && buffer_sp && buffer_sp->GetBytes()) *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); @@ -460,5 +461,5 @@ lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, S return false; stream.Printf("0x%016" PRIx64 " ", value); } - return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj); + return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false); } diff --git a/source/DataFormatters/LibCxxInitializerList.cpp b/source/DataFormatters/LibCxxInitializerList.cpp index e76b0bec95ce..91f1f90507a7 100644 --- a/source/DataFormatters/LibCxxInitializerList.cpp +++ b/source/DataFormatters/LibCxxInitializerList.cpp @@ -107,7 +107,7 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid()) return false; - m_element_size = m_element_type.GetByteSize(); + m_element_size = m_element_type.GetByteSize(nullptr); if (m_element_size > 0) m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency diff --git a/source/DataFormatters/LibCxxVector.cpp b/source/DataFormatters/LibCxxVector.cpp index 26c62afbed2b..d0e6be486d65 100644 --- a/source/DataFormatters/LibCxxVector.cpp +++ b/source/DataFormatters/LibCxxVector.cpp @@ -115,7 +115,7 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() if (!data_type_finder_sp) return false; m_element_type = data_type_finder_sp->GetClangType().GetPointeeType(); - m_element_size = m_element_type.GetByteSize(); + m_element_size = m_element_type.GetByteSize(nullptr); if (m_element_size > 0) { diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp index ff089af58cb7..4c9cd582e642 100644 --- a/source/DataFormatters/TypeSummary.cpp +++ b/source/DataFormatters/TypeSummary.cpp @@ -86,13 +86,30 @@ m_flags(flags) StringSummaryFormat::StringSummaryFormat (const TypeSummaryImpl::Flags& flags, const char *format_cstr) : -TypeSummaryImpl(flags), -m_format() + TypeSummaryImpl(flags), + m_format_str() { - if (format_cstr) - m_format.assign(format_cstr); + SetSummaryString (format_cstr); } +void +StringSummaryFormat::SetSummaryString (const char* format_cstr) +{ + m_format.Clear(); + if (format_cstr && format_cstr[0]) + { + m_format_str = format_cstr; + m_error = FormatEntity::Parse(format_cstr, m_format); + } + else + { + m_format_str.clear(); + m_error.Clear(); + } +} + + + bool StringSummaryFormat::FormatObject (ValueObject *valobj, std::string& retval, @@ -120,7 +137,7 @@ StringSummaryFormat::FormatObject (ValueObject *valobj, } else { - if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, valobj)) + if (FormatEntity::Format(m_format, s, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), valobj, false, false)) { retval.assign(s.GetString()); return true; @@ -138,7 +155,10 @@ StringSummaryFormat::GetDescription () { StreamString sstr; - sstr.Printf ("`%s`%s%s%s%s%s%s%s", m_format.c_str(), + sstr.Printf ("`%s`%s%s%s%s%s%s%s%s%s", + m_format_str.c_str(), + m_error.Fail() ? " error: " : "", + m_error.Fail() ? m_error.AsCString() : "", Cascades() ? "" : " (not cascading)", !DoesPrintChildren(nullptr) ? "" : " (show children)", !DoesPrintValue(nullptr) ? " (hide value)" : "", @@ -153,8 +173,8 @@ CXXFunctionSummaryFormat::CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags Callback impl, const char* description) : TypeSummaryImpl(flags), -m_impl(impl), -m_description(description ? description : "") + m_impl(impl), + m_description(description ? description : "") { } diff --git a/source/DataFormatters/TypeSynthetic.cpp b/source/DataFormatters/TypeSynthetic.cpp index 13c1c7508b68..b150b2bb6ee3 100644 --- a/source/DataFormatters/TypeSynthetic.cpp +++ b/source/DataFormatters/TypeSynthetic.cpp @@ -68,18 +68,24 @@ size_t TypeFilterImpl::FrontEnd::GetIndexOfChildWithName (const ConstString &name) { const char* name_cstr = name.GetCString(); - for (size_t i = 0; i < filter->GetCount(); i++) + if (name_cstr) { - const char* expr_cstr = filter->GetExpressionPathAtIndex(i); - if (expr_cstr) + for (size_t i = 0; i < filter->GetCount(); i++) { - if (*expr_cstr == '.') - expr_cstr++; - else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') - expr_cstr += 2; + const char* expr_cstr = filter->GetExpressionPathAtIndex(i); + if (expr_cstr) + { + if (*expr_cstr == '.') + expr_cstr++; + else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') + expr_cstr += 2; + } + if (expr_cstr) + { + if (!::strcmp(name_cstr, expr_cstr)) + return i; + } } - if (!::strcmp(name_cstr, expr_cstr)) - return i; } return UINT32_MAX; } diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp index 2f14721100bc..c3d42cb49ec5 100644 --- a/source/Expression/ASTResultSynthesizer.cpp +++ b/source/Expression/ASTResultSynthesizer.cpp @@ -480,10 +480,10 @@ ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) } void -ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) +ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) { if (m_passthrough) - m_passthrough->HandleVTable(RD, DefinitionRequired); + m_passthrough->HandleVTable(RD); } void diff --git a/source/Expression/ASTStructExtractor.cpp b/source/Expression/ASTStructExtractor.cpp index 2a8b7bc7d8ec..98628dbc92be 100644 --- a/source/Expression/ASTStructExtractor.cpp +++ b/source/Expression/ASTStructExtractor.cpp @@ -186,10 +186,10 @@ ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) } void -ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) +ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) { if (m_passthrough) - m_passthrough->HandleVTable(RD, DefinitionRequired); + m_passthrough->HandleVTable(RD); } void diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp index 4906108401af..d05d9b99df07 100644 --- a/source/Expression/ClangExpressionParser.cpp +++ b/source/Expression/ClangExpressionParser.cpp @@ -329,7 +329,6 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), module_name, m_compiler->getCodeGenOpts(), - m_compiler->getTargetOpts(), *m_llvm_context)); } diff --git a/source/Expression/ClangModulesDeclVendor.cpp b/source/Expression/ClangModulesDeclVendor.cpp index 46adaaff33ce..0800b52e7e99 100644 --- a/source/Expression/ClangModulesDeclVendor.cpp +++ b/source/Expression/ClangModulesDeclVendor.cpp @@ -7,8 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/StreamString.h" +#include // std::once + #include "lldb/Expression/ClangModulesDeclVendor.h" + +#include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -22,7 +25,6 @@ #include "clang/Sema/Lookup.h" #include "clang/Serialization/ASTReader.h" -#include using namespace lldb_private; @@ -289,7 +291,7 @@ ClangModulesDeclVendor::Create(Target &target) "-Werror=non-modular-include-in-framework-module" }; - target.GetPlatform()->AddClangModuleCompilationOptions(compiler_invocation_arguments); + target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments); compiler_invocation_arguments.push_back(ModuleImportBufferName); diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp index 080562e51e91..b3f335f1b314 100644 --- a/source/Expression/ExpressionSourceCode.cpp +++ b/source/Expression/ExpressionSourceCode.cpp @@ -41,13 +41,17 @@ typedef __UINTPTR_TYPE__ uintptr_t; typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef unsigned short unichar; +extern "C" +{ + int printf(const char * __restrict, ...); +} )"; bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const { const char *target_specific_defines = "typedef signed char BOOL;\n"; - static ConstString g_platform_ios_simulator ("PlatformiOSSimulator"); + static ConstString g_platform_ios_simulator ("ios-simulator"); if (Target *target = exe_ctx.GetTargetPtr()) { diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index e7cb728778e6..9ca9e25907b6 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -199,28 +199,8 @@ IRExecutionUnit::DisassembleFunction (Stream &stream, disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false); InstructionList &instruction_list = disassembler_sp->GetInstructionList(); - const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); - const char *disassemble_format = "${addr-file-or-load}: "; - if (exe_ctx.HasTargetScope()) - { - disassemble_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); - } - - for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize(); - instruction_index < num_instructions; - ++instruction_index) - { - Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get(); - instruction->Dump (&stream, - max_opcode_byte_size, - true, - true, - &exe_ctx, - NULL, - NULL, - disassemble_format); - stream.PutChar('\n'); - } + instruction_list.Dump(&stream, true, true, &exe_ctx); + // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. // I'll fix that but for now, just clear the list and it will go away nicely. disassembler_sp->GetInstructionList().Clear(); @@ -238,6 +218,12 @@ static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Con } } +void +IRExecutionUnit::ReportSymbolLookupError(const ConstString &name) +{ + m_failed_lookups.push_back(name); +} + void IRExecutionUnit::GetRunnableInfo(Error &error, lldb::addr_t &func_addr, @@ -369,6 +355,33 @@ IRExecutionUnit::GetRunnableInfo(Error &error, ReportAllocations(*m_execution_engine_ap); WriteData(process_sp); + if (m_failed_lookups.size()) + { + StreamString ss; + + ss.PutCString("Couldn't lookup symbols:\n"); + + bool emitNewLine = false; + + for (const ConstString &failed_lookup : m_failed_lookups) + { + if (emitNewLine) + ss.PutCString("\n"); + emitNewLine = true; + ss.PutCString(" "); + ss.PutCString(Mangled(failed_lookup).GetDemangledName().AsCString()); + } + + m_failed_lookups.clear(); + + error.SetErrorString(ss.GetData()); + + return; + } + + m_function_load_addr = LLDB_INVALID_ADDRESS; + m_function_end_load_addr = LLDB_INVALID_ADDRESS; + for (JittedFunction &jitted_function : m_jitted_functions) { jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr); @@ -604,6 +617,114 @@ IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size, return return_value; } +uint64_t +IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SymbolContextList sc_list; + + ExecutionContextScope *exe_scope = m_parent.GetBestExecutionContextScope(); + + lldb::TargetSP target_sp = exe_scope->CalculateTarget(); + + const char *name = Name.c_str(); + + ConstString bare_name_cs(name); + ConstString name_cs; + + if (name[0] == '_') + name_cs = ConstString(name + 1); + + if (!target_sp) + { + if (log) + log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = ", + Name.c_str()); + + m_parent.ReportSymbolLookupError(name_cs); + + return 0xbad0bad0; + } + + uint32_t num_matches = 0; + lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); + + if (!name_cs.IsEmpty()) + { + target_sp->GetImages().FindSymbolsWithNameAndType(name_cs, lldb::eSymbolTypeAny, sc_list); + num_matches = sc_list.GetSize(); + } + + if (!num_matches) + { + target_sp->GetImages().FindSymbolsWithNameAndType(bare_name_cs, lldb::eSymbolTypeAny, sc_list); + num_matches = sc_list.GetSize(); + } + + lldb::addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + + for (uint32_t i=0; iGetType() == lldb::eSymbolTypeUndefined) + continue; + + const Address *sym_address = &sym_ctx.symbol->GetAddress(); + + if (!sym_address || !sym_address->IsValid()) + continue; + + symbol_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target_sp); + + if (symbol_load_addr == LLDB_INVALID_ADDRESS) + { + symbol_load_addr = sym_ctx.symbol->GetAddress().GetLoadAddress(target_sp.get()); + } + } + + if (symbol_load_addr == LLDB_INVALID_ADDRESS && process_sp && name_cs) + { + // Try the Objective-C language runtime. + + ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); + + if (runtime) + symbol_load_addr = runtime->LookupRuntimeSymbol(name_cs); + } + + if (symbol_load_addr == LLDB_INVALID_ADDRESS) + { + if (log) + log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = ", + name); + + m_parent.ReportSymbolLookupError(bare_name_cs); + + return 0xbad0bad0; + } + + if (log) + log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64, + name, + symbol_load_addr); + + if (symbol_load_addr == 0) + return 0xbad00add; + + return symbol_load_addr; +} + +void * +IRExecutionUnit::MemoryManager::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + assert (sizeof(void *) == 8); + + return (void*)getSymbolAddress(Name); +} + lldb::addr_t IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address) { diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp index 8e75c32183ec..42390b35fdde 100644 --- a/source/Expression/IRForTarget.cpp +++ b/source/Expression/IRForTarget.cpp @@ -590,7 +590,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) &result_decl->getASTContext()); } - if (m_result_type.GetBitSize() == 0) + if (m_result_type.GetBitSize(nullptr) == 0) { lldb_private::StreamString type_desc_stream; m_result_type.DumpTypeDescription(&type_desc_stream); @@ -617,7 +617,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) if (log) log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, m_result_name.GetCString(), - m_result_type.GetByteSize()); + m_result_type.GetByteSize(nullptr)); // Construct a new result global and set up its metadata @@ -1518,7 +1518,7 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) value_type = global_variable->getType(); } - const uint64_t value_size = clang_type.GetByteSize(); + const uint64_t value_size = clang_type.GetByteSize(nullptr); lldb::offset_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull; if (log) diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp index b11921635e5a..f1f2f99eed5e 100644 --- a/source/Expression/Materializer.cpp +++ b/source/Expression/Materializer.cpp @@ -49,7 +49,7 @@ Materializer::AddStructMember (Entity &entity) void Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type) { - m_size = type.GetByteSize(); + m_size = type.GetByteSize(nullptr); uint32_t bit_alignment = type.GetTypeBitAlign(); @@ -780,7 +780,7 @@ class EntityResultVariable : public Materializer::Entity const lldb::addr_t load_addr = process_address + m_offset; - size_t byte_size = m_type.GetByteSize(); + size_t byte_size = m_type.GetByteSize(nullptr); size_t bit_align = m_type.GetTypeBitAlign(); size_t byte_align = (bit_align + 7) / 8; diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index b82fbea90c6c..a127d58b2767 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -24,6 +24,20 @@ using namespace lldb_private; using namespace lldb_private::line_editor; +// Workaround for what looks like an OS X-specific issue, but other platforms +// may benefit from something similar if issues arise. The libedit library +// doesn't explicitly initialize the curses termcap library, which it gets away +// with until TERM is set to VT100 where it stumbles over an implementation +// assumption that may not exist on other platforms. The setupterm() function +// would normally require headers that don't work gracefully in this context, so +// the function declaraction has been hoisted here. +#if defined(__APPLE__) +extern "C" { + int setupterm(char *term, int fildes, int *errret); +} +#define USE_SETUPTERM_WORKAROUND +#endif + // Editline uses careful cursor management to achieve the illusion of editing a multi-line block of text // with a single line editor. Preserving this illusion requires fairly careful management of cursor // state. Read and understand the relationship between DisplayInput(), MoveCursor(), SetCurrentLine(), @@ -1313,6 +1327,10 @@ Editline::GetLine (std::string &line, bool &interrupted) m_editor_getting_char = false; m_revert_cursor_index = -1; +#ifdef USE_SETUPTERM_WORKAROUND + setupterm((char *)0, fileno(m_output_file), (int *)0); +#endif + int count; auto input = el_wgets (m_editline, &count); @@ -1359,6 +1377,9 @@ Editline::GetLines (int first_line_number, StringList &lines, bool &interrupted) m_revert_cursor_index = -1; while (m_editor_status == EditorStatus::Editing) { +#ifdef USE_SETUPTERM_WORKAROUND + setupterm((char *)0, fileno(m_output_file), (int *)0); +#endif int count; m_current_line_rows = -1; el_wpush (m_editline, EditLineConstString("\x1b[^")); // Revert to the existing line content diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index c3c77835ce86..946f3dd6fef5 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -288,6 +288,8 @@ File::Open (const char *path, uint32_t options, uint32_t permissions) #ifndef _WIN32 if (options & eOpenOptionNonBlocking) oflag |= O_NONBLOCK; + if (options & eOpenOptionCloseOnExec) + oflag |= O_CLOEXEC; #else oflag |= O_BINARY; #endif @@ -742,8 +744,9 @@ File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP if (num_bytes > bytes_left) num_bytes = bytes_left; + size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); std::unique_ptr data_heap_ap; - data_heap_ap.reset(new DataBufferHeap(num_bytes + (null_terminate ? 1 : 0), '\0')); + data_heap_ap.reset(new DataBufferHeap(num_bytes_plus_nul_char, '\0')); if (data_heap_ap.get()) { @@ -752,8 +755,8 @@ File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP { // Make sure we read exactly what we asked for and if we got // less, adjust the array - if (num_bytes < data_heap_ap->GetByteSize()) - data_heap_ap->SetByteSize(num_bytes); + if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) + data_heap_ap->SetByteSize(num_bytes_plus_nul_char); data_buffer_sp.reset(data_heap_ap.release()); return error; } diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp index 0af0556d30c9..6a6de53cd311 100644 --- a/source/Host/common/FileSpec.cpp +++ b/source/Host/common/FileSpec.cpp @@ -65,7 +65,7 @@ FileSpec::ResolveUsername (llvm::SmallVectorImpl &path) if (path.empty() || path[0] != '~') return; - llvm::StringRef path_str(path.data()); + llvm::StringRef path_str(path.data(), path.size()); size_t slash_pos = path_str.find_first_of("/", 1); if (slash_pos == 1 || path.size() == 1) { @@ -240,6 +240,12 @@ void FileSpec::Normalize(llvm::SmallVectorImpl &path, PathSyntax syntax) return; std::replace(path.begin(), path.end(), '\\', '/'); + // Windows path can have \\ slashes which can be changed by replace + // call above to //. Here we remove the duplicate. + auto iter = std::unique ( path.begin(), path.end(), + []( char &c1, char &c2 ){ + return (c1 == '/' && c2 == '/');}); + path.erase(iter, path.end()); } void FileSpec::DeNormalize(llvm::SmallVectorImpl &path, PathSyntax syntax) @@ -1330,8 +1336,7 @@ FileSpec::IsSourceImplementationFile () const ConstString extension (GetFileNameExtension()); if (extension) { - static RegularExpression g_source_file_regex ("^(c|m|mm|cpp|c\\+\\+|cxx|cc|cp|s|asm|f|f77|f90|f95|f03|for|ftn|fpp|ada|adb|ads)$", - REG_EXTENDED | REG_ICASE); + static RegularExpression g_source_file_regex ("^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|[cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO][rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])$"); return g_source_file_regex.Execute (extension.GetCString()); } return false; diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index c8daa175d1bd..30f5c8683060 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C includes #include #include @@ -48,20 +46,21 @@ #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/MonitoringProcessLauncher.h" +#include "lldb/Host/Predicate.h" #include "lldb/Host/ProcessLauncher.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/lldb-private-forward.h" +#include "llvm/Support/FileSystem.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Target/TargetList.h" +#include "lldb/Target/UnixSignals.h" #include "lldb/Utility/CleanUp.h" +#include "llvm/ADT/SmallString.h" #if defined(_WIN32) #include "lldb/Host/windows/ProcessLauncherWindows.h" @@ -170,7 +169,7 @@ MonitorChildProcessThreadFunction (void *arg) { log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); if (log) - log->Printf("%s ::wait_pid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); + log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); // Wait for all child processes #if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) @@ -233,9 +232,9 @@ MonitorChildProcessThreadFunction (void *arg) if (log) log->Printf ("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i) => pid = %" PRIi32 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i", function, - wait_pid, - options, pid, + options, + wait_pid, status, status_cstr, signal, @@ -1053,12 +1052,6 @@ Host::SetCrashDescription (const char *description) { } -lldb::pid_t -Host::LaunchApplication (const FileSpec &app_file_spec) -{ - return LLDB_INVALID_PROCESS_ID; -} - #endif #if !defined (__linux__) && !defined (__FreeBSD__) && !defined (__NetBSD__) diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index d65b79698384..9816c1ebf080 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -23,61 +23,57 @@ #include "llvm/Support/raw_ostream.h" #include +#include // std::once using namespace lldb; using namespace lldb_private; namespace { -void -CleanupProcessSpecificLLDBTempDir() -{ - // Get the process specific LLDB temporary directory and delete it. - FileSpec tmpdir_file_spec; - if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - return; + void + CleanupProcessSpecificLLDBTempDir() + { + // Get the process specific LLDB temporary directory and delete it. + FileSpec tmpdir_file_spec; + if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + return; - // Remove the LLDB temporary directory if we have one. Set "recurse" to - // true to all files that were created for the LLDB process can be cleaned up. - FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true); -} - -struct HostInfoBaseFields -{ - uint32_t m_number_cpus; - std::string m_vendor_string; - std::string m_os_string; - std::string m_host_triple; - - ArchSpec m_host_arch_32; - ArchSpec m_host_arch_64; - - FileSpec m_lldb_so_dir; - FileSpec m_lldb_support_exe_dir; - FileSpec m_lldb_headers_dir; - FileSpec m_lldb_python_dir; - FileSpec m_lldb_clang_resource_dir; - FileSpec m_lldb_system_plugin_dir; - FileSpec m_lldb_user_plugin_dir; - FileSpec m_lldb_tmp_dir; -}; - -HostInfoBaseFields *g_fields = nullptr; -} - -#define COMPUTE_LLDB_PATH(compute_function, member_var) \ - { \ - static bool is_initialized = false; \ - static bool success = false; \ - if (!is_initialized) \ - { \ - is_initialized = true; \ - success = HostInfo::compute_function(member_var); \ - } \ - if (success) \ - result = &member_var; \ + // Remove the LLDB temporary directory if we have one. Set "recurse" to + // true to all files that were created for the LLDB process can be cleaned up. + FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true); } + //---------------------------------------------------------------------- + // The HostInfoBaseFields is a work around for windows not supporting + // static variables correctly in a thread safe way. Really each of the + // variables in HostInfoBaseFields should live in the functions in which + // they are used and each one should be static, but the work around is + // in place to avoid this restriction. Ick. + //---------------------------------------------------------------------- + + struct HostInfoBaseFields + { + uint32_t m_number_cpus; + std::string m_vendor_string; + std::string m_os_string; + std::string m_host_triple; + + ArchSpec m_host_arch_32; + ArchSpec m_host_arch_64; + + FileSpec m_lldb_so_dir; + FileSpec m_lldb_support_exe_dir; + FileSpec m_lldb_headers_dir; + FileSpec m_lldb_python_dir; + FileSpec m_lldb_clang_resource_dir; + FileSpec m_lldb_system_plugin_dir; + FileSpec m_lldb_user_plugin_dir; + FileSpec m_lldb_tmp_dir; + }; + + HostInfoBaseFields *g_fields = nullptr; +} + void HostInfoBase::Initialize() { @@ -87,13 +83,10 @@ HostInfoBase::Initialize() uint32_t HostInfoBase::GetNumberCPUS() { - static bool is_initialized = false; - if (!is_initialized) - { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { g_fields->m_number_cpus = std::thread::hardware_concurrency(); - is_initialized = true; - } - + }); return g_fields->m_number_cpus; } @@ -106,53 +99,40 @@ HostInfoBase::GetMaxThreadNameLength() llvm::StringRef HostInfoBase::GetVendorString() { - static bool is_initialized = false; - if (!is_initialized) - { - const ArchSpec &host_arch = HostInfo::GetArchitecture(); - const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName(); - g_fields->m_vendor_string.assign(str_ref.begin(), str_ref.end()); - is_initialized = true; - } + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str()); + }); return g_fields->m_vendor_string; } llvm::StringRef HostInfoBase::GetOSString() { - static bool is_initialized = false; - if (!is_initialized) - { - const ArchSpec &host_arch = HostInfo::GetArchitecture(); - const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName(); - g_fields->m_os_string.assign(str_ref.begin(), str_ref.end()); - is_initialized = true; - } + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName()); + }); return g_fields->m_os_string; } llvm::StringRef HostInfoBase::GetTargetTriple() { - static bool is_initialized = false; - if (!is_initialized) - { - const ArchSpec &host_arch = HostInfo::GetArchitecture(); - g_fields->m_host_triple = host_arch.GetTriple().getTriple(); - is_initialized = true; - } + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple(); + }); return g_fields->m_host_triple; } const ArchSpec & HostInfoBase::GetArchitecture(ArchitectureKind arch_kind) { - static bool is_initialized = false; - if (!is_initialized) - { + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64); - is_initialized = true; - } + }); // If an explicit 32 or 64-bit architecture was requested, return that. if (arch_kind == eArchKind32) @@ -174,52 +154,123 @@ HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec) return false; #endif - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); FileSpec *result = nullptr; switch (type) { case lldb::ePathTypeLLDBShlibDir: - COMPUTE_LLDB_PATH(ComputeSharedLibraryDirectory, g_fields->m_lldb_so_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_so_dir; + } break; case lldb::ePathTypeSupportExecutableDir: - COMPUTE_LLDB_PATH(ComputeSupportExeDirectory, g_fields->m_lldb_support_exe_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", - g_fields->m_lldb_support_exe_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", + g_fields->m_lldb_support_exe_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_support_exe_dir; + } break; case lldb::ePathTypeHeaderDir: - COMPUTE_LLDB_PATH(ComputeHeaderDirectory, g_fields->m_lldb_headers_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_headers_dir; + } break; case lldb::ePathTypePythonDir: - COMPUTE_LLDB_PATH(ComputePythonDirectory, g_fields->m_lldb_python_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_python_dir; + } break; case lldb::ePathTypeClangDir: - COMPUTE_LLDB_PATH(ComputeClangDirectory, g_fields->m_lldb_clang_resource_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_clang_resource_dir; + } break; case lldb::ePathTypeLLDBSystemPlugins: - COMPUTE_LLDB_PATH(ComputeSystemPluginsDirectory, g_fields->m_lldb_system_plugin_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", - g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", + g_fields->m_lldb_system_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_system_plugin_dir; + } break; case lldb::ePathTypeLLDBUserPlugins: - COMPUTE_LLDB_PATH(ComputeUserPluginsDirectory, g_fields->m_lldb_user_plugin_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", - g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", + g_fields->m_lldb_user_plugin_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_user_plugin_dir; + } break; case lldb::ePathTypeLLDBTempSystemDir: - COMPUTE_LLDB_PATH(ComputeTempFileDirectory, g_fields->m_lldb_tmp_dir) - if (log) - log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); + { + static std::once_flag g_once_flag; + static bool success = false; + std::call_once(g_once_flag, []() { + success = HostInfo::ComputeTempFileDirectory (g_fields->m_lldb_tmp_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str()); + }); + if (success) + result = &g_fields->m_lldb_tmp_dir; + } break; } @@ -327,6 +378,7 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6 arch_32.SetTriple(triple); break; + case llvm::Triple::ppc64: case llvm::Triple::x86_64: arch_64.SetTriple(triple); arch_32.SetTriple(triple.get32BitArchVariant()); @@ -335,7 +387,6 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6 case llvm::Triple::aarch64: case llvm::Triple::mips64: case llvm::Triple::sparcv9: - case llvm::Triple::ppc64: arch_64.SetTriple(triple); break; } diff --git a/source/Host/common/NativeBreakpoint.cpp b/source/Host/common/NativeBreakpoint.cpp index 284d7d11d6ce..622b4eab1726 100644 --- a/source/Host/common/NativeBreakpoint.cpp +++ b/source/Host/common/NativeBreakpoint.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "NativeBreakpoint.h" +#include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/lldb-defines.h" #include "lldb/Core/Error.h" diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp index ecd0624bde09..94d0b3756da4 100644 --- a/source/Host/common/NativeBreakpointList.cpp +++ b/source/Host/common/NativeBreakpointList.cpp @@ -1,4 +1,4 @@ -//===-- NativeBreakpointList.h ----------------------------------*- C++ -*-===// +//===-- NativeBreakpointList.cpp --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "NativeBreakpointList.h" +#include "lldb/Host/common/NativeBreakpointList.h" #include "lldb/Core/Log.h" -#include "NativeBreakpoint.h" +#include "lldb/Host/common/NativeBreakpoint.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index e192f19a8896..ff7310d2d45a 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -7,17 +7,17 @@ // //===----------------------------------------------------------------------===// -#include "NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" -#include "lldb/Target/NativeRegisterContext.h" +#include "lldb/Host/common/NativeRegisterContext.h" -#include "NativeThreadProtocol.h" -#include "SoftwareBreakpoint.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Host/common/SoftwareBreakpoint.h" using namespace lldb; using namespace lldb_private; @@ -39,6 +39,7 @@ NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) : m_delegates_mutex (Mutex::eMutexTypeRecursive), m_delegates (), m_breakpoint_list (), + m_watchpoint_list (), m_terminal_fd (-1), m_stop_id (0) { @@ -159,6 +160,12 @@ NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const return true; } +const NativeWatchpointList::WatchpointMap& +NativeProcessProtocol::GetWatchpointMap () const +{ + return m_watchpoint_list.GetWatchpointMap(); +} + uint32_t NativeProcessProtocol::GetMaxWatchpoints () const { @@ -199,9 +206,6 @@ NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t w Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - // FIXME save the watchpoint on the set of process watchpoint vars - // so we can add them to a thread each time a new thread is registered. - // Update the thread list UpdateThreads (); @@ -261,15 +265,12 @@ NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t w return thread_error; } } - return Error (); + return m_watchpoint_list.Add (addr, size, watch_flags, hardware); } Error NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) { - // FIXME remove the watchpoint on the set of process watchpoint vars - // so we can add them to a thread each time a new thread is registered. - // Update the thread list UpdateThreads (); @@ -292,7 +293,8 @@ NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr) overall_error = thread_error; } } - return overall_error; + const Error error = m_watchpoint_list.Remove(addr); + return overall_error.Fail() ? overall_error : error; } bool @@ -400,6 +402,10 @@ void NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates) { Mutex::Locker locker (m_state_mutex); + + if (state == m_state) + return; + m_state = state; if (StateIsStoppedState (state, false)) diff --git a/source/Target/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp similarity index 98% rename from source/Target/NativeRegisterContext.cpp rename to source/Host/common/NativeRegisterContext.cpp index d84e2279a459..42a9c91a63a0 100644 --- a/source/Target/NativeRegisterContext.cpp +++ b/source/Host/common/NativeRegisterContext.cpp @@ -7,15 +7,15 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Target/NativeRegisterContext.h" +#include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/lldb-private-log.h" -#include "Host/common/NativeProcessProtocol.h" -#include "Host/common/NativeThreadProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" using namespace lldb; using namespace lldb_private; @@ -297,6 +297,12 @@ NativeRegisterContext::ClearHardwareWatchpoint (uint32_t hw_index) return false; } +Error +NativeRegisterContext::ClearAllHardwareWatchpoints () +{ + return Error ("not implemented"); +} + bool NativeRegisterContext::HardwareSingleStep (bool enable) { diff --git a/source/Target/NativeRegisterContextRegisterInfo.cpp b/source/Host/common/NativeRegisterContextRegisterInfo.cpp similarity index 87% rename from source/Target/NativeRegisterContextRegisterInfo.cpp rename to source/Host/common/NativeRegisterContextRegisterInfo.cpp index e37014546646..0d7c6eced757 100644 --- a/source/Target/NativeRegisterContextRegisterInfo.cpp +++ b/source/Host/common/NativeRegisterContextRegisterInfo.cpp @@ -9,7 +9,7 @@ #include "lldb/lldb-types.h" #include "lldb/lldb-private-forward.h" -#include "lldb/Target/NativeRegisterContextRegisterInfo.h" +#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h" using namespace lldb_private; @@ -28,6 +28,12 @@ NativeRegisterContextRegisterInfo::GetRegisterCount () const return m_register_info_interface_up->GetRegisterCount (); } +uint32_t +NativeRegisterContextRegisterInfo::GetUserRegisterCount () const +{ + return m_register_info_interface_up->GetUserRegisterCount (); +} + const RegisterInfo * NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const { diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp index 6cef5b1fa2d2..ea406e9ef2c6 100644 --- a/source/Host/common/NativeThreadProtocol.cpp +++ b/source/Host/common/NativeThreadProtocol.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "NativeThreadProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" -#include "NativeProcessProtocol.h" -#include "lldb/Target/NativeRegisterContext.h" -#include "SoftwareBreakpoint.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/common/SoftwareBreakpoint.h" using namespace lldb; using namespace lldb_private; @@ -73,25 +73,3 @@ NativeThreadProtocol::GetProcess () { return m_process_wp.lock (); } - -uint32_t -NativeThreadProtocol::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const -{ - // Default: no translation. Do the real translation where there - // is access to the host signal numbers. - switch (stop_info.reason) - { - case eStopReasonSignal: - return stop_info.details.signal.signo; - break; - - case eStopReasonException: - // FIXME verify the way to specify pass-thru here. - return static_cast (stop_info.details.exception.type); - break; - - default: - assert (0 && "unexpected stop_info.reason found"); - return 0; - } -} diff --git a/source/Host/common/NativeWatchpointList.cpp b/source/Host/common/NativeWatchpointList.cpp new file mode 100644 index 000000000000..209d213b8e50 --- /dev/null +++ b/source/Host/common/NativeWatchpointList.cpp @@ -0,0 +1,35 @@ +//===-- NativeWatchpointList.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/common/NativeWatchpointList.h" + +#include "lldb/Core/Log.h" + +using namespace lldb; +using namespace lldb_private; + +Error +NativeWatchpointList::Add (addr_t addr, size_t size, uint32_t watch_flags, bool hardware) +{ + m_watchpoints[addr] = {addr, size, watch_flags, hardware}; + return Error (); +} + +Error +NativeWatchpointList::Remove (addr_t addr) +{ + m_watchpoints.erase(addr); + return Error (); +} + +const NativeWatchpointList::WatchpointMap& +NativeWatchpointList::GetWatchpointMap () const +{ + return m_watchpoints; +} diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index a6118eef7b79..b5559fffb45d 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -15,8 +15,8 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/SocketAddress.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" -#include "lldb/Interpreter/Args.h" #ifdef __ANDROID_NDK__ #include @@ -190,7 +190,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inhe Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("ConnectionFileDescriptor::SocketListen (%s)", host_and_port.data()); + log->Printf ("Socket::TcpListen (%s)", host_and_port.data()); std::string host_str; std::string port_str; @@ -222,7 +222,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inhe // as port zero is a special code for "find an open port // for me". if (port == 0) - port = listen_socket->GetPortNumber(); + port = listen_socket->GetLocalPortNumber(); // Set the port predicate since when doing a listen://: // it often needs to accept the incoming connection which is a blocking @@ -230,7 +230,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, bool child_processes_inhe // us to wait for the port predicate to be set to a non-zero value from // another thread in an efficient manor. if (predicate) - predicate->SetValue(port, eBroadcastAlways); + predicate->SetValue (port, eBroadcastAlways); socket = listen_socket.release(); } @@ -533,13 +533,18 @@ Socket::DecodeHostAndPort(llvm::StringRef host_and_port, if (regex_match.GetMatchAtIndex (host_and_port.data(), 1, host_str) && regex_match.GetMatchAtIndex (host_and_port.data(), 2, port_str)) { - port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); - if (port != INT32_MIN) + bool ok = false; + port = StringConvert::ToUInt32 (port_str.c_str(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { if (error_ptr) error_ptr->Clear(); return true; } + // port is too large + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port.data()); + return false; } } @@ -547,10 +552,13 @@ Socket::DecodeHostAndPort(llvm::StringRef host_and_port, // a port with an empty host. host_str.clear(); port_str.clear(); - port = Args::StringToSInt32(host_and_port.data(), INT32_MIN); - if (port != INT32_MIN) + bool ok = false; + port = StringConvert::ToUInt32 (host_and_port.data(), UINT32_MAX, 10, &ok); + if (ok && port < UINT16_MAX) { port_str = host_and_port; + if (error_ptr) + error_ptr->Clear(); return true; } @@ -688,7 +696,7 @@ int Socket::SetOption(int level, int option_name, int option_value) return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); } -uint16_t Socket::GetPortNumber(const NativeSocket& socket) +uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket) { // We bound to port zero, so we need to figure out which port we actually bound to if (socket >= 0) @@ -702,7 +710,47 @@ uint16_t Socket::GetPortNumber(const NativeSocket& socket) } // Return the port number that is being used by the socket. -uint16_t Socket::GetPortNumber() const +uint16_t Socket::GetLocalPortNumber() const { - return GetPortNumber(m_socket); + return GetLocalPortNumber (m_socket); } + +std::string Socket::GetLocalIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + +uint16_t Socket::GetRemotePortNumber () const +{ + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort (); + } + return 0; +} + +std::string Socket::GetRemoteIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket >= 0) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + + diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 6231631934df..fd7fbac952e3 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -21,6 +21,58 @@ // Other libraries and framework includes // Project includes +// WindowsXP needs an inet_ntop implementation +#ifdef _WIN32 + +#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs +#define INET6_ADDRSTRLEN 46 +#endif + +// TODO: implement shortened form "::" for runs of zeros +const char* inet_ntop(int af, const void * src, + char * dst, socklen_t size) +{ + if (size==0) + { + return nullptr; + } + + switch (af) + { + case AF_INET: + { + { + const char* formatted = inet_ntoa(*static_cast(src)); + if (formatted && strlen(formatted) < size) + { + strncpy(dst, formatted, size); + return dst; + } + } + return nullptr; + case AF_INET6: + { + char tmp[INET6_ADDRSTRLEN] = {0}; + const uint16_t* src16 = static_cast(src); + int full_size = _snprintf(tmp, sizeof(tmp), + "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), + ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7]) + ); + if (full_size < static_cast(size)) + { + strncpy(dst,tmp,size); + return dst; + } + return nullptr; + } + } + } + return nullptr; +} +#endif + + using namespace lldb_private; //---------------------------------------------------------------------- @@ -124,6 +176,26 @@ SocketAddress::SetFamily (sa_family_t family) #endif } +std::string +SocketAddress::GetIPAddress () const +{ + char str[INET6_ADDRSTRLEN] = {0}; + switch (GetFamily()) + { + case AF_INET: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str))) + { + return str; + } + case AF_INET6: + if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str))) + { + return str; + } + } + return ""; +} + uint16_t SocketAddress::GetPort () const { diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp index d9d1fa67156f..67f472b88f5c 100644 --- a/source/Host/common/SoftwareBreakpoint.cpp +++ b/source/Host/common/SoftwareBreakpoint.cpp @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "SoftwareBreakpoint.h" +#include "lldb/Host/common/SoftwareBreakpoint.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/Debug.h" #include "lldb/Host/Mutex.h" -#include "NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" using namespace lldb_private; diff --git a/source/Host/common/StringConvert.cpp b/source/Host/common/StringConvert.cpp new file mode 100644 index 000000000000..0a8e75f4b877 --- /dev/null +++ b/source/Host/common/StringConvert.cpp @@ -0,0 +1,93 @@ +//===-- StringConvert.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Host/StringConvert.h" + +namespace lldb_private { + +namespace StringConvert { + +int32_t +ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + const long sval = ::strtol (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); + return (int32_t)sval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +uint32_t +ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + const unsigned long uval = ::strtoul (s, &end, base); + if (*end == '\0') + { + if (success_ptr) + *success_ptr = (uval <= UINT32_MAX); + return (uint32_t)uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +int64_t +ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + int64_t uval = ::strtoll (s, &end, base); + if (*end == '\0') + { + if (success_ptr) *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +uint64_t +ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr) +{ + if (s && s[0]) + { + char *end = nullptr; + uint64_t uval = ::strtoull (s, &end, base); + if (*end == '\0') + { + if (success_ptr) *success_ptr = true; + return uval; // All characters were used, return the result + } + } + if (success_ptr) *success_ptr = false; + return fail_value; +} + +} +} diff --git a/source/Host/common/ThreadLauncher.cpp b/source/Host/common/ThreadLauncher.cpp index ec7da325bf92..c19a23361d81 100644 --- a/source/Host/common/ThreadLauncher.cpp +++ b/source/Host/common/ThreadLauncher.cpp @@ -38,6 +38,16 @@ ThreadLauncher::LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_fu error.SetError(::GetLastError(), eErrorTypeWin32); #else + + // ASAN instrumentation adds a lot of bookkeeping overhead on stack frames. +#if __has_feature(address_sanitizer) + const size_t eight_megabytes = 8 * 1024 * 1024; + if (min_stack_byte_size < eight_megabytes) + { + min_stack_byte_size += eight_megabytes; + } +#endif + pthread_attr_t *thread_attr_ptr = NULL; pthread_attr_t thread_attr; bool destroy_attr = false; diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 38ddc0a49220..fe70c33bf5ae 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -19,6 +19,7 @@ #include "lldb/Host/IOObject.h" #include "lldb/Host/SocketAddress.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/StringConvert.h" // C Includes #include @@ -41,6 +42,7 @@ #include "lldb/lldb-private-log.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" #include "lldb/Host/Socket.h" @@ -142,7 +144,7 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) if (strstr(s, "listen://") == s) { // listen://HOST:PORT - return SocketListen(s + strlen("listen://"), error_ptr); + return SocketListenAndAccept(s + strlen("listen://"), error_ptr); } else if (strstr(s, "accept://") == s) { @@ -173,7 +175,7 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) // that is already opened (possibly from a service or other source). s += strlen("fd://"); bool success = false; - int fd = Args::StringToSInt32(s, -1, 0, &success); + int fd = StringConvert::ToSInt32(s, -1, 0, &success); if (success) { @@ -219,6 +221,7 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) m_read_sp.reset(new File(fd, false)); m_write_sp.reset(new File(fd, false)); } + m_uri.assign(s); return eConnectionStatusSuccess; } } @@ -351,6 +354,7 @@ ConnectionFileDescriptor::Disconnect(Error *error_ptr) if (error_ptr) *error_ptr = error.Fail() ? error : error2; + m_uri.clear(); m_shutting_down = false; return status; } @@ -510,6 +514,12 @@ ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatu return bytes_sent; } +std::string +ConnectionFileDescriptor::GetURI() +{ + return m_uri; +} + // This ConnectionFileDescriptor::BytesAvailable() uses select(). // // PROS: @@ -700,7 +710,12 @@ ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *erro *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus @@ -712,11 +727,16 @@ ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *err *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; } ConnectionStatus -ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) +ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) { m_port_predicate.SetValue(0, eBroadcastNever); @@ -741,7 +761,14 @@ ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + StreamString strm; + strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber()); + m_uri.swap(strm.GetString()); + return eConnectionStatusSuccess; } ConnectionStatus @@ -753,7 +780,12 @@ ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } ConnectionStatus @@ -766,7 +798,12 @@ ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) *error_ptr = error; m_write_sp.reset(send_socket); m_read_sp.reset(recv_socket); - return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(s); + return eConnectionStatusSuccess; } uint16_t diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index 02838ec5124e..1650f1e7979b 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -9,12 +9,16 @@ #include "lldb/Host/posix/PipePosix.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/FileSystem.h" #include #include #include #include +#include #include #include #include @@ -182,6 +186,37 @@ PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) return error; } +Error +PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl& name) +{ + llvm::SmallString named_pipe_path; + llvm::SmallString pipe_spec((prefix + ".%%%%%%").str()); + FileSpec tmpdir_file_spec; + tmpdir_file_spec.Clear(); + if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + { + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } + else + { + tmpdir_file_spec.AppendPathComponent("/tmp"); + tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); + } + + // It's possible that another process creates the target path after we've + // verified it's available but before we create it, in which case we + // should try again. + Error error; + do { + llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath().c_str(), named_pipe_path); + error = CreateNew(named_pipe_path, child_process_inherit); + } while (error.GetError() == EEXIST); + + if (error.Success()) + name = named_pipe_path; + return error; +} + Error PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) { diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp index 93933802f57c..4f0219fb858b 100644 --- a/source/Interpreter/Args.cpp +++ b/source/Interpreter/Args.cpp @@ -19,14 +19,13 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Process.h" -//#include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" -//#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -166,7 +165,7 @@ Args::SetCommandString (const char *command) if (command && command[0]) { static const char *k_space_separators = " \t"; - static const char *k_space_separators_with_slash_and_quotes = " \t \\'\""; + static const char *k_escapable_characters = " \t\\'\""; const char *arg_end = nullptr; const char *arg_pos; for (arg_pos = command; @@ -202,7 +201,7 @@ Args::SetCommandString (const char *command) do { - arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos; + arg_end = ::strcspn (arg_pos, k_escapable_characters) + arg_pos; switch (arg_end[0]) { @@ -216,7 +215,6 @@ Args::SetCommandString (const char *command) arg.append (arg_piece_start); arg_complete = true; break; - case '\\': // Backslash character switch (arg_end[1]) @@ -228,22 +226,21 @@ Args::SetCommandString (const char *command) break; default: - if (quote_char == '\0') + // Only consider this two-character sequence an escape sequence if we're unquoted and + // the character after the backslash is a whitelisted escapable character. Otherwise + // leave the character sequence untouched. + if (quote_char == '\0' && (nullptr != strchr(k_escapable_characters, arg_end[1]))) { arg.append (arg_piece_start, arg_end - arg_piece_start); - if (arg_end[1] != '\0') - { - arg.append (arg_end + 1, 1); - arg_pos = arg_end + 2; - arg_piece_start = arg_pos; - } + arg.append (arg_end + 1, 1); + arg_pos = arg_end + 2; + arg_piece_start = arg_pos; } else arg_pos = arg_end + 2; break; } break; - case '"': case '\'': case '`': @@ -722,77 +719,6 @@ Args::Clear () m_args_quote_char.clear(); } -int32_t -Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - const long sval = ::strtol (s, &end, base); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN)); - return (int32_t)sval; // All characters were used, return the result - } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} - -uint32_t -Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - const unsigned long uval = ::strtoul (s, &end, base); - if (*end == '\0') - { - if (success_ptr) - *success_ptr = (uval <= UINT32_MAX); - return (uint32_t)uval; // All characters were used, return the result - } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} - - -int64_t -Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - int64_t uval = ::strtoll (s, &end, base); - if (*end == '\0') - { - if (success_ptr) *success_ptr = true; - return uval; // All characters were used, return the result - } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} - -uint64_t -Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr) -{ - if (s && s[0]) - { - char *end = nullptr; - uint64_t uval = ::strtoull (s, &end, base); - if (*end == '\0') - { - if (success_ptr) *success_ptr = true; - return uval; // All characters were used, return the result - } - } - if (success_ptr) *success_ptr = false; - return fail_value; -} - lldb::addr_t Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr) { @@ -878,7 +804,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add if (regex_match.GetMatchAtIndex(s, 3, str)) { - offset = Args::StringToUInt64(str.c_str(), 0, 0, &success); + offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success); if (success) { diff --git a/source/Interpreter/CommandHistory.cpp b/source/Interpreter/CommandHistory.cpp index 26996a625642..bbe64b446acc 100644 --- a/source/Interpreter/CommandHistory.cpp +++ b/source/Interpreter/CommandHistory.cpp @@ -7,8 +7,10 @@ // //===----------------------------------------------------------------------===// +#include + #include "lldb/Interpreter/CommandHistory.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" using namespace lldb; using namespace lldb_private; @@ -47,7 +49,7 @@ CommandHistory::FindString (const char* input_str) const if (input_str[1] == '-') { bool success; - size_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success); + size_t idx = StringConvert::ToUInt32 (input_str+2, 0, 0, &success); if (!success) return nullptr; if (idx > m_history.size()) @@ -66,7 +68,7 @@ CommandHistory::FindString (const char* input_str) const else { bool success; - uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success); + uint32_t idx = StringConvert::ToUInt32 (input_str+1, 0, 0, &success); if (!success) return nullptr; if (idx >= m_history.size()) diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 176a1fc9a3b0..6318b80a29ed 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -1170,17 +1170,25 @@ void CommandInterpreter::GetHelp (CommandReturnObject &result, uint32_t cmd_types) { + const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue(); + if (help_prologue != NULL) + { + OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue); + } + CommandObject::CommandMap::const_iterator pos; size_t max_len = FindLongestCommandWord (m_command_dict); if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) { - - result.AppendMessage("The following is a list of built-in, permanent debugger commands:"); + result.AppendMessage("Debugger commands:"); result.AppendMessage(""); for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) { + if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0)) + continue; + OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), max_len); } @@ -1190,8 +1198,9 @@ CommandInterpreter::GetHelp (CommandReturnObject &result, if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) { - result.AppendMessage("The following is a list of your current command abbreviations " - "(see 'help command alias' for more info):"); + result.AppendMessageWithFormat("Current command abbreviations " + "(type '%shelp command alias' for more info):\n", + GetCommandPrefix()); result.AppendMessage(""); max_len = FindLongestCommandWord (m_alias_dict); @@ -1212,7 +1221,7 @@ CommandInterpreter::GetHelp (CommandReturnObject &result, if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) { - result.AppendMessage ("The following is a list of your current user-defined commands:"); + result.AppendMessage ("Current user-defined commands:"); result.AppendMessage(""); max_len = FindLongestCommandWord (m_user_dict); for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) @@ -1223,7 +1232,8 @@ CommandInterpreter::GetHelp (CommandReturnObject &result, result.AppendMessage(""); } - result.AppendMessage("For more information on any particular command, try 'help '."); + result.AppendMessageWithFormat("For more information on any command, type '%shelp '.\n", + GetCommandPrefix()); } CommandObject * @@ -2496,6 +2506,13 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) } } +const char * +CommandInterpreter::GetCommandPrefix() +{ + const char * prefix = GetDebugger().GetIOHandlerCommandPrefix(); + return prefix == NULL ? "" : prefix; +} + PlatformSP CommandInterpreter::GetPlatform (bool prefer_target_platform) { @@ -2885,6 +2902,66 @@ CommandInterpreter::SetSynchronous (bool value) m_synchronous_execution = value; } +void +CommandInterpreter::OutputFormattedHelpText (Stream &strm, + const char *prefix, + const char *help_text) +{ + const uint32_t max_columns = m_debugger.GetTerminalWidth(); + if (prefix == NULL) + prefix = ""; + + size_t prefix_width = strlen(prefix); + size_t line_width_max = max_columns - prefix_width; + const char *help_text_end = help_text + strlen(help_text); + const char *line_start = help_text; + if (line_width_max < 16) + line_width_max = help_text_end - help_text + prefix_width; + + strm.IndentMore (prefix_width); + while (line_start < help_text_end) + { + // Break each line at the first newline or last space/tab before + // the maximum number of characters that fit on a line. Lines with no + // natural break are left unbroken to wrap. + const char *line_end = help_text_end; + const char *line_scan = line_start; + const char *line_scan_end = help_text_end; + while (line_scan < line_scan_end) + { + char next = *line_scan; + if (next == '\t' || next == ' ') + { + line_end = line_scan; + line_scan_end = line_start + line_width_max; + } + else if (next == '\n' || next == '\0') + { + line_end = line_scan; + break; + } + ++line_scan; + } + + // Prefix the first line, indent subsequent lines to line up + if (line_start == help_text) + strm.Write (prefix, prefix_width); + else + strm.Indent(); + strm.Write (line_start, line_end - line_start); + strm.EOL(); + + // When a line breaks at whitespace consume it before continuing + line_start = line_end; + char next = *line_start; + if (next == '\n') + ++line_start; + else while (next == ' ' || next == '\t') + next = *(++line_start); + } + strm.IndentLess (prefix_width); +} + void CommandInterpreter::OutputFormattedHelpText (Stream &strm, const char *word_text, @@ -2892,79 +2969,9 @@ CommandInterpreter::OutputFormattedHelpText (Stream &strm, const char *help_text, size_t max_word_len) { - const uint32_t max_columns = m_debugger.GetTerminalWidth(); - - int indent_size = max_word_len + strlen (separator) + 2; - - strm.IndentMore (indent_size); - - StreamString text_strm; - text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text); - - size_t len = text_strm.GetSize(); - const char *text = text_strm.GetData(); - if (text[len - 1] == '\n') - { - text_strm.EOL(); - len = text_strm.GetSize(); - } - - if (len < max_columns) - { - // Output it as a single line. - strm.Printf ("%s", text); - } - else - { - // We need to break it up into multiple lines. - bool first_line = true; - int text_width; - size_t start = 0; - size_t end = start; - const size_t final_end = strlen (text); - - while (end < final_end) - { - if (first_line) - text_width = max_columns - 1; - else - text_width = max_columns - indent_size - 1; - - // Don't start the 'text' on a space, since we're already outputting the indentation. - if (!first_line) - { - while ((start < final_end) && (text[start] == ' ')) - start++; - } - - end = start + text_width; - if (end > final_end) - end = final_end; - else - { - // If we're not at the end of the text, make sure we break the line on white space. - while (end > start - && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') - end--; - assert (end > 0); - } - - const size_t sub_len = end - start; - if (start != 0) - strm.EOL(); - if (!first_line) - strm.Indent(); - else - first_line = false; - assert (start <= final_end); - assert (start + sub_len <= final_end); - if (sub_len > 0) - strm.Write (text + start, sub_len); - start = end + 1; - } - } - strm.EOL(); - strm.IndentLess(indent_size); + StreamString prefix_stream; + prefix_stream.Printf (" %-*s %s ", (int)max_word_len, word_text, separator); + OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text); } void @@ -3222,6 +3229,13 @@ CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler) return true; // Don't do any updating when we are running } } + + ScriptInterpreter *script_interpreter = GetScriptInterpreter (false); + if (script_interpreter) + { + if (script_interpreter->Interrupt()) + return true; + } return false; } diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp index efc7c33fa8f6..bde7f58b4cb0 100644 --- a/source/Interpreter/CommandObjectRegexCommand.cpp +++ b/source/Interpreter/CommandObjectRegexCommand.cpp @@ -111,7 +111,7 @@ CommandObjectRegexCommand::AddRegexCommand (const char *re_cstr, const char *com { m_entries.resize(m_entries.size() + 1); // Only add the regular expression if it compiles - if (m_entries.back().regex.Compile (re_cstr, REG_EXTENDED)) + if (m_entries.back().regex.Compile (re_cstr)) { m_entries.back().command.assign (command_cstr); return true; diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp index 7e5e1245a79f..6bb36552d06b 100644 --- a/source/Interpreter/OptionGroupPlatform.cpp +++ b/source/Interpreter/OptionGroupPlatform.cpp @@ -147,3 +147,38 @@ OptionGroupPlatform::SetOptionValue (CommandInterpreter &interpreter, } return error; } + +bool +OptionGroupPlatform::PlatformMatches(const lldb::PlatformSP &platform_sp) const +{ + if (platform_sp) + { + if (!m_platform_name.empty()) + { + if (platform_sp->GetName() != ConstString(m_platform_name.c_str())) + return false; + } + + if (m_sdk_build && m_sdk_build != platform_sp->GetSDKBuild()) + return false; + + if (m_sdk_sysroot && m_sdk_sysroot != platform_sp->GetSDKRootDirectory()) + return false; + + if (m_os_version_major != UINT32_MAX) + { + uint32_t major, minor, update; + if (platform_sp->GetOSVersion (major, minor, update)) + { + if (m_os_version_major != major) + return false; + if (m_os_version_minor != minor) + return false; + if (m_os_version_update != update) + return false; + } + } + return true; + } + return false; +} diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp index b6c63fa44c40..72d7ff597ab2 100644 --- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -16,6 +16,7 @@ // Other libraries and framework includes // Project includes #include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Utility/Utils.h" @@ -89,13 +90,13 @@ OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter, case 'A': ignore_cap = true; break; case 'D': - max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success); + max_depth = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg); break; case 'P': - ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success); + ptr_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg); break; @@ -103,7 +104,7 @@ OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter, case 'Y': if (option_arg) { - no_summary_depth = Args::StringToUInt32 (option_arg, 0, 0, &success); + no_summary_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success); if (!success) error.SetErrorStringWithFormat("invalid pointer depth '%s'", option_arg); } diff --git a/source/Interpreter/OptionValue.cpp b/source/Interpreter/OptionValue.cpp index a08a6127db15..1e4ea23cc075 100644 --- a/source/Interpreter/OptionValue.cpp +++ b/source/Interpreter/OptionValue.cpp @@ -222,6 +222,22 @@ OptionValue::GetAsFormat () const return nullptr; } +OptionValueFormatEntity * +OptionValue::GetAsFormatEntity () +{ + if (GetType () == OptionValue::eTypeFormatEntity) + return static_cast(this); + return nullptr; +} + +const OptionValueFormatEntity * +OptionValue::GetAsFormatEntity () const +{ + if (GetType () == OptionValue::eTypeFormatEntity) + return static_cast(this); + return nullptr; +} + OptionValuePathMappings * OptionValue::GetAsPathMappings () { @@ -452,6 +468,15 @@ OptionValue::SetFormatValue (lldb::Format new_value) return false; } +const FormatEntity::Entry * +OptionValue::GetFormatEntity () const +{ + const OptionValueFormatEntity *option_value = GetAsFormatEntity(); + if (option_value) + return &option_value->GetCurrentValue(); + return nullptr; +} + const RegularExpression * OptionValue::GetRegexValue () const { @@ -563,6 +588,7 @@ OptionValue::GetBuiltinTypeAsCString (Type t) case eTypeFileSpec: return "file"; case eTypeFileSpecList: return "file-list"; case eTypeFormat: return "format"; + case eTypeFormatEntity: return "format-string"; case eTypePathMap: return "path-map"; case eTypeProperties: return "properties"; case eTypeRegex: return "regex"; @@ -583,15 +609,16 @@ OptionValue::CreateValueFromCStringForTypeMask (const char *value_cstr, uint32_t lldb::OptionValueSP value_sp; switch (type_mask) { - case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break; - case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break; - case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break; - case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break; - case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break; - case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break; - case 1u << eTypeString: value_sp.reset(new OptionValueString()); break; - case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break; - case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break; + case 1u << eTypeArch: value_sp.reset(new OptionValueArch()); break; + case 1u << eTypeBoolean: value_sp.reset(new OptionValueBoolean(false)); break; + case 1u << eTypeChar: value_sp.reset(new OptionValueChar('\0')); break; + case 1u << eTypeFileSpec: value_sp.reset(new OptionValueFileSpec()); break; + case 1u << eTypeFormat: value_sp.reset(new OptionValueFormat(eFormatInvalid)); break; + case 1u << eTypeFormatEntity: value_sp.reset(new OptionValueFormatEntity(NULL)); break; + case 1u << eTypeSInt64: value_sp.reset(new OptionValueSInt64()); break; + case 1u << eTypeString: value_sp.reset(new OptionValueString()); break; + case 1u << eTypeUInt64: value_sp.reset(new OptionValueUInt64()); break; + case 1u << eTypeUUID: value_sp.reset(new OptionValueUUID()); break; } if (value_sp) diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp index c0d48c1e7bd2..86d49c9ba3b4 100644 --- a/source/Interpreter/OptionValueArray.cpp +++ b/source/Interpreter/OptionValueArray.cpp @@ -14,6 +14,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Stream.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" using namespace lldb; @@ -97,7 +98,7 @@ OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx, sub_value = end_bracket + 1; std::string index_str (name+1, end_bracket); const size_t array_count = m_values.size(); - int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr); + int32_t idx = StringConvert::ToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr); if (idx != INT32_MAX) { ; @@ -177,7 +178,7 @@ OptionValueArray::SetArgs (const Args &args, VarSetOperationType op) case eVarSetOperationInsertAfter: if (argc > 1) { - uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = GetSize(); if (idx > count) { @@ -225,7 +226,7 @@ OptionValueArray::SetArgs (const Args &args, VarSetOperationType op) for (i=0; i= size) { all_indexes_valid = false; @@ -274,7 +275,7 @@ OptionValueArray::SetArgs (const Args &args, VarSetOperationType op) case eVarSetOperationReplace: if (argc > 1) { - uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = GetSize(); if (idx > count) { diff --git a/source/Interpreter/OptionValueFileSpecLIst.cpp b/source/Interpreter/OptionValueFileSpecLIst.cpp index 7150ad474643..0e696ca91db6 100644 --- a/source/Interpreter/OptionValueFileSpecLIst.cpp +++ b/source/Interpreter/OptionValueFileSpecLIst.cpp @@ -14,6 +14,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Stream.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" using namespace lldb; @@ -57,7 +58,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation case eVarSetOperationReplace: if (argc > 1) { - uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = m_current_value.GetSize(); if (idx > count) { @@ -108,7 +109,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation case eVarSetOperationInsertAfter: if (argc > 1) { - uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = m_current_value.GetSize(); if (idx > count) { @@ -140,7 +141,7 @@ OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperation size_t i; for (i=0; all_indexes_valid && i= 3 && (((argc - 1) & 1) == 0)) { - uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = m_path_mappings.GetSize(); if (idx > count) { @@ -108,7 +109,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation // Must be at least one index + 1 pair of paths, and the pair count must be even if (argc >= 3 && (((argc - 1) & 1) == 0)) { - uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); + uint32_t idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); const uint32_t count = m_path_mappings.GetSize(); if (idx > count) { @@ -141,7 +142,7 @@ OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperation size_t i; for (i=0; all_indexes_valid && iGetValue().get(); + if (value) + return value->GetFormatEntity(); + } + return nullptr; +} OptionValueFileSpec * OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const diff --git a/source/Interpreter/OptionValueRegex.cpp b/source/Interpreter/OptionValueRegex.cpp index f51cf02edf56..fab462f0e704 100644 --- a/source/Interpreter/OptionValueRegex.cpp +++ b/source/Interpreter/OptionValueRegex.cpp @@ -62,7 +62,7 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, case eVarSetOperationReplace: case eVarSetOperationAssign: - if (m_regex.Compile (value_cstr, m_regex.GetCompileFlags())) + if (m_regex.Compile (value_cstr)) { m_value_was_set = true; NotifyValueChanged(); @@ -84,5 +84,5 @@ OptionValueRegex::SetValueFromCString (const char *value_cstr, lldb::OptionValueSP OptionValueRegex::DeepCopy () const { - return OptionValueSP(new OptionValueRegex(m_regex.GetText(), m_regex.GetCompileFlags())); + return OptionValueSP(new OptionValueRegex(m_regex.GetText())); } diff --git a/source/Interpreter/OptionValueSInt64.cpp b/source/Interpreter/OptionValueSInt64.cpp index 1827cc1d873f..c69172921a6d 100644 --- a/source/Interpreter/OptionValueSInt64.cpp +++ b/source/Interpreter/OptionValueSInt64.cpp @@ -14,7 +14,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Stream.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" using namespace lldb; using namespace lldb_private; @@ -51,7 +51,7 @@ OptionValueSInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationAssign: { bool success = false; - int64_t value = Args::StringToSInt64 (value_cstr, 0, 0, &success); + int64_t value = StringConvert::ToSInt64 (value_cstr, 0, 0, &success); if (success) { if (value >= m_min_value && value <= m_max_value) diff --git a/source/Interpreter/OptionValueUInt64.cpp b/source/Interpreter/OptionValueUInt64.cpp index 3e12c030255c..48de433d36c1 100644 --- a/source/Interpreter/OptionValueUInt64.cpp +++ b/source/Interpreter/OptionValueUInt64.cpp @@ -14,7 +14,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Stream.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" using namespace lldb; using namespace lldb_private; @@ -58,7 +58,7 @@ OptionValueUInt64::SetValueFromCString (const char *value_cstr, VarSetOperationT case eVarSetOperationAssign: { bool success = false; - uint64_t value = Args::StringToUInt64 (value_cstr, 0, 0, &success); + uint64_t value = StringConvert::ToUInt64 (value_cstr, 0, 0, &success); if (success) { m_value_was_set = true; diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp index 7f7219fc0d50..5679ef8dd3ba 100644 --- a/source/Interpreter/Property.cpp +++ b/source/Interpreter/Property.cpp @@ -16,7 +16,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/UserSettingsController.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionValues.h" @@ -109,16 +109,21 @@ Property::Property (const PropertyDefinition &definition) : // "definition.default_cstr_value" is NULL, otherwise interpret // "definition.default_cstr_value" as a string value that represents the default // value. - { - Format new_format = eFormatInvalid; - if (definition.default_cstr_value) - Args::StringToFormat (definition.default_cstr_value, new_format, nullptr); - else - new_format = (Format)definition.default_uint_value; - m_value_sp.reset (new OptionValueFormat(new_format)); - } + { + Format new_format = eFormatInvalid; + if (definition.default_cstr_value) + Args::StringToFormat (definition.default_cstr_value, new_format, nullptr); + else + new_format = (Format)definition.default_uint_value; + m_value_sp.reset (new OptionValueFormat(new_format)); + } break; + case OptionValue::eTypeFormatEntity: + // "definition.default_cstr_value" as a string value that represents the default + m_value_sp.reset (new OptionValueFormatEntity(definition.default_cstr_value)); + break; + case OptionValue::eTypePathMap: // "definition.default_uint_value" tells us if notifications should occur for // path mappings @@ -129,7 +134,7 @@ Property::Property (const PropertyDefinition &definition) : // "definition.default_uint_value" is used to the regular expression flags // "definition.default_cstr_value" the default regular expression value // value. - m_value_sp.reset (new OptionValueRegex(definition.default_cstr_value, definition.default_uint_value)); + m_value_sp.reset (new OptionValueRegex(definition.default_cstr_value)); break; case OptionValue::eTypeSInt64: @@ -137,7 +142,7 @@ Property::Property (const PropertyDefinition &definition) : // "definition.default_cstr_value" is NULL, otherwise interpret // "definition.default_cstr_value" as a string value that represents the default // value. - m_value_sp.reset (new OptionValueSInt64(definition.default_cstr_value ? Args::StringToSInt64 (definition.default_cstr_value) : definition.default_uint_value)); + m_value_sp.reset (new OptionValueSInt64(definition.default_cstr_value ? StringConvert::ToSInt64 (definition.default_cstr_value) : definition.default_uint_value)); break; case OptionValue::eTypeUInt64: @@ -145,18 +150,18 @@ Property::Property (const PropertyDefinition &definition) : // "definition.default_cstr_value" is NULL, otherwise interpret // "definition.default_cstr_value" as a string value that represents the default // value. - m_value_sp.reset (new OptionValueUInt64(definition.default_cstr_value ? Args::StringToUInt64 (definition.default_cstr_value) : definition.default_uint_value)); + m_value_sp.reset (new OptionValueUInt64(definition.default_cstr_value ? StringConvert::ToUInt64 (definition.default_cstr_value) : definition.default_uint_value)); break; case OptionValue::eTypeUUID: // "definition.default_uint_value" is not used for a OptionValue::eTypeUUID // "definition.default_cstr_value" can contain a default UUID value - { - UUID uuid; - if (definition.default_cstr_value) - uuid.SetFromCString (definition.default_cstr_value); - m_value_sp.reset (new OptionValueUUID(uuid)); - } + { + UUID uuid; + if (definition.default_cstr_value) + uuid.SetFromCString (definition.default_cstr_value); + m_value_sp.reset (new OptionValueUUID(uuid)); + } break; case OptionValue::eTypeString: diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp index ab151073f9e9..8155cbb189fe 100644 --- a/source/Interpreter/ScriptInterpreterPython.cpp +++ b/source/Interpreter/ScriptInterpreterPython.cpp @@ -103,13 +103,14 @@ ScriptInterpreterPython::Locker::DoAcquireLock() m_GILState = PyGILState_Ensure(); if (log) log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); - + // we need to save the thread state when we first start the command // because we might decide to interrupt it while some action is taking // place outside of Python (e.g. printing to screen, waiting for the network, ...) // in that case, _PyThreadState_Current will be NULL - and we would be unable // to set the asynchronous exception - not a desirable situation m_python_interpreter->SetThreadState (_PyThreadState_Current); + m_python_interpreter->IncrementLockCount(); return true; } @@ -128,6 +129,7 @@ ScriptInterpreterPython::Locker::DoFreeLock() if (log) log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); PyGILState_Release(m_GILState); + m_python_interpreter->DecrementLockCount(); return true; } @@ -166,6 +168,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete m_session_is_active (false), m_pty_slave_is_open (false), m_valid_session (true), + m_lock_count (0), m_command_thread_state (nullptr) { @@ -535,7 +538,7 @@ ScriptInterpreterPython::GetSysModuleDictionary () static std::string GenerateUniqueName (const char* base_name_wanted, uint32_t& functions_counter, - void* name_token = nullptr) + const void* name_token = nullptr) { StreamString sstr; @@ -817,24 +820,7 @@ class IOHandlerPythonInterpreter : virtual bool Interrupt () { - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - - PyThreadState* state = _PyThreadState_Current; - if (!state) - state = m_python->GetThreadState(); - if (state) - { - long tid = state->thread_id; - _PyThreadState_Current = state; - int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); - if (log) - log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p", - tid, num_threads, static_cast(state)); - } - else if (log) - log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL"); - - return false; + return m_python->Interrupt(); } virtual void @@ -869,6 +855,31 @@ ScriptInterpreterPython::ExecuteInterpreterLoop () } } +bool +ScriptInterpreterPython::Interrupt() +{ + Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); + + if (IsExecutingPython()) + { + PyThreadState* state = _PyThreadState_Current; + if (!state) + state = GetThreadState(); + if (state) + { + long tid = state->thread_id; + _PyThreadState_Current = state; + int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); + if (log) + log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads); + return true; + } + } + if (log) + log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt"); + return false; + +} bool ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, ScriptInterpreter::ScriptReturnType return_type, @@ -1243,7 +1254,7 @@ ScriptInterpreterPython::GenerateFunction(const char *signature, const StringLis } bool -ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, void* name_token) +ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const void* name_token) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines (); @@ -1292,7 +1303,7 @@ ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, st bool -ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, void* name_token) +ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, const void* name_token) { static uint32_t num_created_classes = 0; user_input.RemoveBlankLines (); @@ -1795,7 +1806,7 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name } bool -ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token) +ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token) { StringList input; input.SplitIntoLines(oneliner, strlen(oneliner)); @@ -1803,7 +1814,7 @@ ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std:: } bool -ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token) +ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token) { StringList input; input.SplitIntoLines(oneliner, strlen(oneliner)); diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 5073b13f09ab..42acba232de1 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -334,11 +334,11 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread, size_t bit_width = 0; if (clang_type.IsIntegerType (is_signed)) { - bit_width = clang_type.GetBitSize(); + bit_width = clang_type.GetBitSize(nullptr); } else if (clang_type.IsPointerOrReferenceType ()) { - bit_width = clang_type.GetBitSize(); + bit_width = clang_type.GetBitSize(nullptr); } else { @@ -437,7 +437,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (clang_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); switch (bit_width) { diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 465257db31d8..c2ba165afb4a 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -322,11 +322,11 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const size_t bit_width = 0; if (value_type.IsIntegerType (is_signed)) { - bit_width = value_type.GetBitSize(); + bit_width = value_type.GetBitSize(nullptr); } else if (value_type.IsPointerOrReferenceType ()) { - bit_width = value_type.GetBitSize(); + bit_width = value_type.GetBitSize(nullptr); } else { @@ -709,7 +709,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, uint32_t &NSRN, // NSRN (see ABI documentation) DataExtractor &data) { - const size_t byte_size = value_type.GetByteSize(); + const size_t byte_size = value_type.GetByteSize(nullptr); if (byte_size == 0) return false; @@ -728,7 +728,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, { if (!base_type) return false; - const size_t base_byte_size = base_type.GetByteSize(); + const size_t base_byte_size = base_type.GetByteSize(nullptr); printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size); uint32_t data_offset = 0; @@ -871,7 +871,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_ if (!reg_ctx) return return_valobj_sp; - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); if (type_flags & eTypeIsScalar || diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 9a1ea11cbae7..ee5b9298721b 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -552,7 +552,7 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread.GetProcess().get(), current_stack_argument); @@ -560,7 +560,7 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread.GetProcess().get(), current_stack_argument); @@ -672,7 +672,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -732,6 +732,10 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, return return_valobj_sp; } +// This defines the CFA as esp+4 +// the saved pc is at CFA-4 (i.e. esp+0) +// The saved esp is CFA+0 + bool ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) { @@ -745,12 +749,18 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) row->SetCFARegister (sp_reg_num); row->SetCFAOffset (4); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("i386 at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); return true; } +// This defines the CFA as ebp+8 +// The saved pc is at CFA-4 (i.e. ebp+4) +// The saved ebp is at CFA-8 (i.e. ebp+0) +// The saved esp is CFA+0 + bool ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) { @@ -786,6 +796,11 @@ ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info) } // v. http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 +// +// This document ("OS X ABI Function Call Guide", chapter "IA-32 Function Calling Conventions") +// says that the following registers on i386 are preserved aka non-volatile aka callee-saved: +// +// ebx, ebp, esi, edi, esp bool ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info) diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index adb3313d1a30..741afebfcb8b 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -444,7 +444,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread, argument_register_ids, @@ -454,7 +454,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread, argument_register_ids, @@ -524,7 +524,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); if (bit_width <= 64) { DataExtractor data; @@ -588,7 +588,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +637,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,13 +681,11 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0); - if (altivec_reg == NULL) - altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) @@ -742,7 +740,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(); + const size_t bit_width = return_clang_type.GetBitSize(nullptr); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); @@ -784,7 +782,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(); + const size_t field_bit_width = field_clang_type.GetBitSize(nullptr); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index 46f1e1023f0a..88c18fb6f202 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -444,7 +444,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread, argument_register_ids, @@ -454,7 +454,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread, argument_register_ids, @@ -524,7 +524,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); if (bit_width <= 64) { DataExtractor data; @@ -588,7 +588,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +637,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,13 +681,11 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0); - if (altivec_reg == NULL) - altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) @@ -742,7 +740,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(); + const size_t bit_width = return_clang_type.GetBitSize(nullptr); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); @@ -784,7 +782,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(); + const size_t field_bit_width = field_clang_type.GetBitSize(nullptr); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 776e7fea67c7..71d99c8c65d2 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -510,7 +510,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), is_signed, thread, argument_register_ids, @@ -520,7 +520,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(), + clang_type.GetBitSize(nullptr), false, thread, argument_register_ids, @@ -590,7 +590,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(); + size_t bit_width = clang_type.GetBitSize(nullptr); if (bit_width <= 64) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -658,7 +658,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -707,7 +707,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -755,7 +755,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(); + const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { @@ -821,7 +821,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(); + const size_t bit_width = return_clang_type.GetBitSize(nullptr); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); @@ -869,7 +869,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(); + const size_t field_bit_width = field_clang_type.GetBitSize(nullptr); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -1070,6 +1070,10 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c return return_valobj_sp; } +// This defines the CFA as rsp+8 +// the saved pc is at CFA-8 (i.e. rsp+0) +// The saved rsp is CFA+0 + bool ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) { @@ -1083,12 +1087,18 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) row->SetCFARegister (sp_reg_num); row->SetCFAOffset (8); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("x86_64 at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); return true; } +// This defines the CFA as rbp+16 +// The saved pc is at CFA-8 (i.e. rbp+8) +// The saved rbp is at CFA-16 (i.e. rbp+0) +// The saved rsp is CFA+0 + bool ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) { @@ -1132,6 +1142,7 @@ ABISysV_x86_64::RegisterIsVolatile (const RegisterInfo *reg_info) // (this doc is also commonly referred to as the x86-64/AMD64 psABI) // Edited by Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell // current version is 0.99.6 released 2012-07-02 at http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf +// It's being revised & updated at https://github.com/hjl-tools/x86-psABI/ bool ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 97ddbef0e307..2f9012222c02 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -371,7 +371,7 @@ class InstructionLLVMC : public lldb_private::Instruction } } - static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); + static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"); RegularExpression::Match matches(3); @@ -457,7 +457,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns std::unique_ptr symbolizer_up(curr_target->createMCSymbolizer(triple, NULL, DisassemblerLLVMC::SymbolLookupCallback, (void *) &owner, - m_context_ap.get(), RelInfo.release())); + m_context_ap.get(), std::move(RelInfo))); m_disasm_ap->setSymbolizer(std::move(symbolizer_up)); diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index d8279e44e14a..a504e801daac 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -19,6 +19,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "llvm/Support/Path.h" + #include "DYLDRendezvous.h" using namespace lldb; @@ -238,9 +240,7 @@ DYLDRendezvous::UpdateSOEntriesForAddition() return false; // Only add shared libraries and not the executable. - // On Linux this is indicated by an empty path in the entry. - // On FreeBSD it is the name of the executable. - if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + if (SOEntryIsMainExecutable(entry)) continue; pos = std::find(m_soentries.begin(), m_soentries.end(), entry); @@ -276,6 +276,28 @@ DYLDRendezvous::UpdateSOEntriesForDeletion() return true; } +bool +DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) +{ + // On Linux the executable is indicated by an empty path in the entry. On + // FreeBSD it is the full path to the executable. On Android, it is the + // basename of the executable. + + auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); + auto os_type = triple.getOS(); + auto env_type = triple.getEnvironment(); + + switch (os_type) { + case llvm::Triple::FreeBSD: + return ::strcmp(entry.path.c_str(), m_exe_path) == 0; + case llvm::Triple::Linux: + return entry.path.empty() || (env_type == llvm::Triple::Android && + llvm::sys::path::filename(m_exe_path) == entry.path); + default: + return false; + } +} + bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) { @@ -290,9 +312,7 @@ DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) return false; // Only add shared libraries and not the executable. - // On Linux this is indicated by an empty path in the entry. - // On FreeBSD it is the name of the executable. - if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + if (SOEntryIsMainExecutable(entry)) continue; entry_list.push_back(entry); diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index ca0089317998..51fcd9b7d397 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -247,6 +247,9 @@ class DYLDRendezvous { bool UpdateSOEntriesForDeletion(); + bool + SOEntryIsMainExecutable(const SOEntry &entry); + /// Reads the current list of shared objects according to the link map /// supplied by the runtime linker. bool diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 6b0b6f5cc8b8..fdef1026f3c6 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -542,6 +542,9 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset() return LLDB_INVALID_ADDRESS; ObjectFile *exe = module->GetObjectFile(); + if (!exe) + return LLDB_INVALID_ADDRESS; + Address file_entry = exe->GetEntryPointAddress(); if (!file_entry.IsValid()) diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index a6c74f3f1fc4..50537eb119f2 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -291,7 +291,8 @@ ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType // the Itanium ABI. if (language == eLanguageTypeC_plus_plus || language == eLanguageTypeC_plus_plus_03 || - language == eLanguageTypeC_plus_plus_11) + language == eLanguageTypeC_plus_plus_11 || + language == eLanguageTypeC_plus_plus_14) return new ItaniumABILanguageRuntime (process); else return NULL; diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index b1be0f5b1fe1..5b72728c2b48 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -288,82 +288,6 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source, } // if we are still here rsync has failed - let's try the slow way before giving up } - - if (log) - log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)", - source.GetPath().c_str(), - destination.GetPath().c_str(), - uid, - gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN - // open - // read, write, read, write, ... - // close - // chown uid:gid dst - if (log) - log->Printf("[PutFile] Using block by block transfer....\n"); - - uint32_t source_open_options = File::eOpenOptionRead; - if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) - source_open_options |= File::eOpenoptionDontFollowSymlinks; - - File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); - Error error; - uint32_t permissions = source_file.GetPermissions(error); - if (permissions == 0) - permissions = lldb::eFilePermissionsFileDefault; - - if (!source_file.IsValid()) - return Error("unable to open source file"); - lldb::user_id_t dest_file = OpenFile (destination, - File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, - permissions, - error); - if (log) - log->Printf ("dest_file = %" PRIu64 "\n", dest_file); - if (error.Fail()) - return error; - if (dest_file == UINT64_MAX) - return Error("unable to open target file"); - lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); - uint64_t offset = 0; - while (error.Success()) - { - size_t bytes_read = buffer_sp->GetByteSize(); - error = source_file.Read(buffer_sp->GetBytes(), bytes_read); - if (bytes_read) - { - const uint64_t bytes_written = WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error); - offset += bytes_written; - if (bytes_written != bytes_read) - { - // We didn't write the correct numbe of bytes, so adjust - // the file position in the source file we are reading from... - source_file.SeekFromStart(offset); - } - } - else - break; - } - CloseFile(dest_file, error); - if (uid == UINT32_MAX && gid == UINT32_MAX) - return error; - // This is remopve, don't chown a local file... -// std::string dst_path (destination.GetPath()); -// if (chown_file(this,dst_path.c_str(),uid,gid) != 0) -// return Error("unable to perform chown"); - - - uint64_t src_md5[2]; - uint64_t dst_md5[2]; - - if (FileSystem::CalculateMD5 (source, src_md5[0], src_md5[1]) && CalculateMD5 (destination, dst_md5[0], dst_md5[1])) - { - if (src_md5[0] != dst_md5[0] || src_md5[1] != dst_md5[1]) - { - error.SetErrorString("md5 checksum of installed file doesn't match, installation failed"); - } - } - return error; } return Platform::PutFile(source,destination,uid,gid); } @@ -841,8 +765,12 @@ PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, // Set UnixSignals appropriately. process_sp->SetUnixSignals (Host::GetUnixSignals ()); - ListenerSP listener_sp (new Listener("lldb.PlatformPOSIX.attach.hijack")); - attach_info.SetHijackListener(listener_sp); + auto listener_sp = attach_info.GetHijackListener(); + if (listener_sp == nullptr) + { + listener_sp.reset(new Listener("lldb.PlatformPOSIX.attach.hijack")); + attach_info.SetHijackListener(listener_sp); + } process_sp->HijackProcessEvents(listener_sp.get()); error = process_sp->Attach (attach_info); } diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 43eae4d906ec..ec2084aaf98c 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -30,6 +30,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "Utility/UriParser.h" + using namespace lldb; using namespace lldb_private; @@ -105,12 +107,76 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { + // copied from PlatformRemoteiOS + Error error; - //error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented"); - if (m_gdb_client.GetFileExists(module_spec.GetFileSpec())) - return error; - // TODO: get the remote end to somehow resolve this file - error.SetErrorString("file not found on remote end"); + // Nothing special to do here, just use the actual file and architecture + + ModuleSpec resolved_module_spec(module_spec); + + // Resolve any executable within an apk on Android? + //Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); + + if (resolved_module_spec.GetFileSpec().Exists()) + { + if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid()) + { + error = ModuleList::GetSharedModule (resolved_module_spec, + exe_module_sp, + NULL, + NULL, + NULL); + + if (exe_module_sp && exe_module_sp->GetObjectFile()) + return error; + exe_module_sp.reset(); + } + // No valid architecture was specified or the exact arch wasn't + // found so ask the platform for the architectures that we should be + // using (in the correct order) and see if we can find a match that way + StreamString arch_names; + for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) + { + error = ModuleList::GetSharedModule (resolved_module_spec, + exe_module_sp, + NULL, + NULL, + NULL); + // Did we find an executable using one of the + if (error.Success()) + { + if (exe_module_sp && exe_module_sp->GetObjectFile()) + break; + else + error.SetErrorToGenericError(); + } + + if (idx > 0) + arch_names.PutCString (", "); + arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); + } + + if (error.Fail() || !exe_module_sp) + { + if (resolved_module_spec.GetFileSpec().Readable()) + { + error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", + resolved_module_spec.GetFileSpec().GetPath().c_str(), + GetPluginName().GetCString(), + arch_names.GetString().c_str()); + } + else + { + error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); + } + } + } + else + { + error.SetErrorStringWithFormat ("'%s' does not exist", + resolved_module_spec.GetFileSpec().GetPath().c_str()); + } + return error; } @@ -146,6 +212,15 @@ PlatformRemoteGDBServer::~PlatformRemoteGDBServer() bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { + ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); + + // TODO: 64 bit systems should also advertize support for 32 bit arch + // unknown CPU, we just support the one arch + if (idx == 0) + { + arch = remote_arch; + return true; + } return false; } @@ -252,6 +327,17 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args) { const char *url = args.GetArgumentAtIndex(0); m_gdb_client.SetConnection (new ConnectionFileDescriptor()); + + // we're going to reuse the hostname when we connect to the debugserver + std::string scheme; + int port; + std::string path; + if ( !UriParser::Parse(url, scheme, m_platform_hostname, port, path) ) + { + error.SetErrorString("invalid uri"); + return error; + } + const ConnectionStatus status = m_gdb_client.Connect(url, &error); if (status == eConnectionStatusSuccess) { @@ -344,14 +430,30 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); Error error; - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (log) log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__); - m_gdb_client.SetSTDIN ("/dev/null"); - m_gdb_client.SetSTDOUT ("/dev/null"); - m_gdb_client.SetSTDERR ("/dev/null"); + auto num_file_actions = launch_info.GetNumFileActions (); + for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) + { + const auto file_action = launch_info.GetFileActionAtIndex (i); + if (file_action->GetAction () != FileAction::eFileActionOpen) + continue; + switch(file_action->GetFD()) + { + case STDIN_FILENO: + m_gdb_client.SetSTDIN (file_action->GetPath()); + break; + case STDOUT_FILENO: + m_gdb_client.SetSTDOUT (file_action->GetPath()); + break; + case STDERR_FILENO: + m_gdb_client.SetSTDERR (file_action->GetPath()); + break; + } + } + m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError)); @@ -389,7 +491,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) std::string error_str; if (m_gdb_client.GetLaunchSuccess (error_str)) { - pid = m_gdb_client.GetCurrentProcessID (); + const auto pid = m_gdb_client.GetCurrentProcessID (false); if (pid != LLDB_INVALID_PROCESS_ID) { launch_info.SetProcessID (pid); @@ -400,7 +502,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) { if (log) log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__); - // FIXME isn't this an error condition? Do we need to set an error here? Check with Greg. + error.SetErrorString ("failed to get PID"); } } else @@ -417,6 +519,14 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) return error; } +Error +PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid) +{ + if (!m_gdb_client.KillSpawnedProcess(pid)) + return Error("failed to kill remote spawned process"); + return Error(); +} + lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, @@ -483,7 +593,7 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i const int connect_url_len = ::snprintf (connect_url, sizeof(connect_url), "connect://%s:%u", - override_hostname ? override_hostname : GetHostname (), + override_hostname ? override_hostname : m_platform_hostname.c_str(), port + port_offset); assert (connect_url_len < (int)sizeof(connect_url)); error = process_sp->ConnectRemote (NULL, connect_url); @@ -576,13 +686,19 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, const int connect_url_len = ::snprintf (connect_url, sizeof(connect_url), "connect://%s:%u", - override_hostname ? override_hostname : GetHostname (), + override_hostname ? override_hostname : m_platform_hostname.c_str(), port + port_offset); assert (connect_url_len < (int)sizeof(connect_url)); - error = process_sp->ConnectRemote (NULL, connect_url); + error = process_sp->ConnectRemote(nullptr, connect_url); if (error.Success()) + { + auto listener = attach_info.GetHijackListener(); + if (listener != nullptr) + process_sp->HijackProcessEvents(listener.get()); error = process_sp->Attach(attach_info); - else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) + } + + if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) { m_gdb_client.KillSpawnedProcess(debugserver_pid); } diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 90b16b8b8fa9..a928c4695f79 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -86,7 +86,10 @@ class PlatformRemoteGDBServer : public lldb_private::Platform virtual lldb_private::Error LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); - + + virtual lldb_private::Error + KillProcess (const lldb::pid_t pid); + virtual lldb::ProcessSP DebugProcess (lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, @@ -212,6 +215,7 @@ class PlatformRemoteGDBServer : public lldb_private::Platform protected: GDBRemoteCommunicationClient m_gdb_client; std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to + std::string m_platform_hostname; private: DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer); diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 84e35ba22644..b33f83303971 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -30,7 +30,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" - +#include "Plugins/Process/POSIX/CrashReason.h" #include "POSIXThread.h" #include "ProcessFreeBSD.h" #include "ProcessPOSIXLog.h" @@ -994,6 +994,11 @@ ProcessMonitor::Launch(LaunchArgs *args) if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) exit(ePtraceFailed); + // terminal has already dupped the tty descriptors to stdin/out/err. + // This closes original fd from which they were copied (and avoids + // leaking descriptors to the debugged process. + terminal.CloseSlaveFileDescriptor(); + // Do not inherit setgid powers. if (setgid(getgid()) != 0) exit(eSetGidFailed); @@ -1306,27 +1311,14 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, if (log) log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo)); - if (signo == SIGSEGV) { + switch (signo) + { + case SIGSEGV: + case SIGILL: + case SIGFPE: + case SIGBUS: lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGILL) { - lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGFPE) { - lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); - } - - if (signo == SIGBUS) { - lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); - ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); + const auto reason = GetCrashReason(*info); return ProcessMessage::Crash(tid, reason, signo, fault_addr); } @@ -1335,141 +1327,6 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, return ProcessMessage::Signal(tid, signo); } -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGSEGV); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGSEGV"); - break; - case SEGV_MAPERR: - reason = ProcessMessage::eInvalidAddress; - break; - case SEGV_ACCERR: - reason = ProcessMessage::ePrivilegedAddress; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGILL); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGILL"); - break; - case ILL_ILLOPC: - reason = ProcessMessage::eIllegalOpcode; - break; - case ILL_ILLOPN: - reason = ProcessMessage::eIllegalOperand; - break; - case ILL_ILLADR: - reason = ProcessMessage::eIllegalAddressingMode; - break; - case ILL_ILLTRP: - reason = ProcessMessage::eIllegalTrap; - break; - case ILL_PRVOPC: - reason = ProcessMessage::ePrivilegedOpcode; - break; - case ILL_PRVREG: - reason = ProcessMessage::ePrivilegedRegister; - break; - case ILL_COPROC: - reason = ProcessMessage::eCoprocessorError; - break; - case ILL_BADSTK: - reason = ProcessMessage::eInternalStackError; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGFPE); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGFPE"); - break; - case FPE_INTDIV: - reason = ProcessMessage::eIntegerDivideByZero; - break; - case FPE_INTOVF: - reason = ProcessMessage::eIntegerOverflow; - break; - case FPE_FLTDIV: - reason = ProcessMessage::eFloatDivideByZero; - break; - case FPE_FLTOVF: - reason = ProcessMessage::eFloatOverflow; - break; - case FPE_FLTUND: - reason = ProcessMessage::eFloatUnderflow; - break; - case FPE_FLTRES: - reason = ProcessMessage::eFloatInexactResult; - break; - case FPE_FLTINV: - reason = ProcessMessage::eFloatInvalidOperation; - break; - case FPE_FLTSUB: - reason = ProcessMessage::eFloatSubscriptRange; - break; - } - - return reason; -} - -ProcessMessage::CrashReason -ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) -{ - ProcessMessage::CrashReason reason; - assert(info->si_signo == SIGBUS); - - reason = ProcessMessage::eInvalidCrashReason; - - switch (info->si_code) - { - default: - assert(false && "unexpected si_code for SIGBUS"); - break; - case BUS_ADRALN: - reason = ProcessMessage::eIllegalAlignment; - break; - case BUS_ADRERR: - reason = ProcessMessage::eIllegalAddress; - break; - case BUS_OBJERR: - reason = ProcessMessage::eHardwareError; - break; - } - - return reason; -} - void ProcessMonitor::ServeOperation(OperationArgs *args) { @@ -1706,7 +1563,10 @@ ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) if (target_fd == -1) return false; - return (dup2(target_fd, fd) == -1) ? false : true; + if (dup2(target_fd, fd) == -1) + return false; + + return (close(target_fd) == -1) ? false : true; } void @@ -1727,11 +1587,10 @@ ProcessMonitor::StopMonitor() StopOpThread(); sem_destroy(&m_operation_pending); sem_destroy(&m_operation_done); - - // Note: ProcessPOSIX passes the m_terminal_fd file descriptor to - // Process::SetSTDIOFileDescriptor, which in turn transfers ownership of - // the descriptor to a ConnectionFileDescriptor object. Consequently - // even though still has the file descriptor, we shouldn't close it here. + if (m_terminal_fd >= 0) { + close(m_terminal_fd); + m_terminal_fd = -1; + } } // FIXME: On Linux, when a new thread is created, we receive to notifications, diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 935fd85ed37a..4ae963c89a2f 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -79,7 +79,8 @@ class ProcessMonitor /// Reads from this file descriptor yield both the standard output and /// standard error of this debugee. Even if stderr and stdout were /// redirected on launch it may still happen that data is available on this - /// descriptor (if the inferior process opens /dev/tty, for example). + /// descriptor (if the inferior process opens /dev/tty, for example). This descriptor is + /// closed after a call to StopMonitor(). /// /// If this monitor was attached to an existing process this method returns /// -1. @@ -311,18 +312,6 @@ class ProcessMonitor MonitorSignal(ProcessMonitor *monitor, const siginfo_t *info, lldb::pid_t pid); - static ProcessMessage::CrashReason - GetCrashReasonForSIGSEGV(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGILL(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGFPE(const siginfo_t *info); - - static ProcessMessage::CrashReason - GetCrashReasonForSIGBUS(const siginfo_t *info); - void DoOperation(Operation *op); diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp new file mode 100644 index 000000000000..4dd91a6f1de8 --- /dev/null +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -0,0 +1,315 @@ +//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CrashReason.h" + +#include + +namespace { + +void +AppendFaultAddr (std::string& str, lldb::addr_t addr) +{ + std::stringstream ss; + ss << " (fault address: 0x" << std::hex << addr << ")"; + str += ss.str(); +} + +CrashReason +GetCrashReasonForSIGSEGV(const siginfo_t& info) +{ + assert(info.si_signo == SIGSEGV); + + switch (info.si_code) + { + case SI_KERNEL: + // Linux will occasionally send spurious SI_KERNEL codes. + // (this is poorly documented in sigaction) + // One way to get this is via unaligned SIMD loads. + return CrashReason::eInvalidAddress; // for lack of anything better + case SEGV_MAPERR: + return CrashReason::eInvalidAddress; + case SEGV_ACCERR: + return CrashReason::ePrivilegedAddress; + } + + assert(false && "unexpected si_code for SIGSEGV"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGILL(const siginfo_t& info) +{ + assert(info.si_signo == SIGILL); + + switch (info.si_code) + { + case ILL_ILLOPC: + return CrashReason::eIllegalOpcode; + case ILL_ILLOPN: + return CrashReason::eIllegalOperand; + case ILL_ILLADR: + return CrashReason::eIllegalAddressingMode; + case ILL_ILLTRP: + return CrashReason::eIllegalTrap; + case ILL_PRVOPC: + return CrashReason::ePrivilegedOpcode; + case ILL_PRVREG: + return CrashReason::ePrivilegedRegister; + case ILL_COPROC: + return CrashReason::eCoprocessorError; + case ILL_BADSTK: + return CrashReason::eInternalStackError; + } + + assert(false && "unexpected si_code for SIGILL"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGFPE(const siginfo_t& info) +{ + assert(info.si_signo == SIGFPE); + + switch (info.si_code) + { + case FPE_INTDIV: + return CrashReason::eIntegerDivideByZero; + case FPE_INTOVF: + return CrashReason::eIntegerOverflow; + case FPE_FLTDIV: + return CrashReason::eFloatDivideByZero; + case FPE_FLTOVF: + return CrashReason::eFloatOverflow; + case FPE_FLTUND: + return CrashReason::eFloatUnderflow; + case FPE_FLTRES: + return CrashReason::eFloatInexactResult; + case FPE_FLTINV: + return CrashReason::eFloatInvalidOperation; + case FPE_FLTSUB: + return CrashReason::eFloatSubscriptRange; + } + + assert(false && "unexpected si_code for SIGFPE"); + return CrashReason::eInvalidCrashReason; +} + +CrashReason +GetCrashReasonForSIGBUS(const siginfo_t& info) +{ + assert(info.si_signo == SIGBUS); + + switch (info.si_code) + { + case BUS_ADRALN: + return CrashReason::eIllegalAlignment; + case BUS_ADRERR: + return CrashReason::eIllegalAddress; + case BUS_OBJERR: + return CrashReason::eHardwareError; + } + + assert(false && "unexpected si_code for SIGBUS"); + return CrashReason::eInvalidCrashReason; +} + +} + +std::string +GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr) +{ + std::string str; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case CrashReason::eInvalidAddress: + str = "invalid address"; + AppendFaultAddr (str, fault_addr); + break; + case CrashReason::ePrivilegedAddress: + str = "address access protected"; + AppendFaultAddr (str, fault_addr); + break; + case CrashReason::eIllegalOpcode: + str = "illegal instruction"; + break; + case CrashReason::eIllegalOperand: + str = "illegal instruction operand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "illegal addressing mode"; + break; + case CrashReason::eIllegalTrap: + str = "illegal trap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "privileged instruction"; + break; + case CrashReason::ePrivilegedRegister: + str = "privileged register"; + break; + case CrashReason::eCoprocessorError: + str = "coprocessor error"; + break; + case CrashReason::eInternalStackError: + str = "internal stack error"; + break; + case CrashReason::eIllegalAlignment: + str = "illegal alignment"; + break; + case CrashReason::eIllegalAddress: + str = "illegal address"; + break; + case CrashReason::eHardwareError: + str = "hardware error"; + break; + case CrashReason::eIntegerDivideByZero: + str = "integer divide by zero"; + break; + case CrashReason::eIntegerOverflow: + str = "integer overflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "floating point divide by zero"; + break; + case CrashReason::eFloatOverflow: + str = "floating point overflow"; + break; + case CrashReason::eFloatUnderflow: + str = "floating point underflow"; + break; + case CrashReason::eFloatInexactResult: + str = "inexact floating point result"; + break; + case CrashReason::eFloatInvalidOperation: + str = "invalid floating point operation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "invalid floating point subscript range"; + break; + } + + return str; +} + +const char * +CrashReasonAsString (CrashReason reason) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in ascii for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = nullptr; + + switch (reason) + { + case CrashReason::eInvalidCrashReason: + str = "eInvalidCrashReason"; + break; + + // SIGSEGV crash reasons. + case CrashReason::eInvalidAddress: + str = "eInvalidAddress"; + break; + case CrashReason::ePrivilegedAddress: + str = "ePrivilegedAddress"; + break; + + // SIGILL crash reasons. + case CrashReason::eIllegalOpcode: + str = "eIllegalOpcode"; + break; + case CrashReason::eIllegalOperand: + str = "eIllegalOperand"; + break; + case CrashReason::eIllegalAddressingMode: + str = "eIllegalAddressingMode"; + break; + case CrashReason::eIllegalTrap: + str = "eIllegalTrap"; + break; + case CrashReason::ePrivilegedOpcode: + str = "ePrivilegedOpcode"; + break; + case CrashReason::ePrivilegedRegister: + str = "ePrivilegedRegister"; + break; + case CrashReason::eCoprocessorError: + str = "eCoprocessorError"; + break; + case CrashReason::eInternalStackError: + str = "eInternalStackError"; + break; + + // SIGBUS crash reasons: + case CrashReason::eIllegalAlignment: + str = "eIllegalAlignment"; + break; + case CrashReason::eIllegalAddress: + str = "eIllegalAddress"; + break; + case CrashReason::eHardwareError: + str = "eHardwareError"; + break; + + // SIGFPE crash reasons: + case CrashReason::eIntegerDivideByZero: + str = "eIntegerDivideByZero"; + break; + case CrashReason::eIntegerOverflow: + str = "eIntegerOverflow"; + break; + case CrashReason::eFloatDivideByZero: + str = "eFloatDivideByZero"; + break; + case CrashReason::eFloatOverflow: + str = "eFloatOverflow"; + break; + case CrashReason::eFloatUnderflow: + str = "eFloatUnderflow"; + break; + case CrashReason::eFloatInexactResult: + str = "eFloatInexactResult"; + break; + case CrashReason::eFloatInvalidOperation: + str = "eFloatInvalidOperation"; + break; + case CrashReason::eFloatSubscriptRange: + str = "eFloatSubscriptRange"; + break; + } +#endif + + return str; +} + +CrashReason +GetCrashReason(const siginfo_t& info) +{ + switch(info.si_signo) + { + case SIGSEGV: + return GetCrashReasonForSIGSEGV(info); + case SIGBUS: + return GetCrashReasonForSIGBUS(info); + case SIGFPE: + return GetCrashReasonForSIGFPE(info); + case SIGILL: + return GetCrashReasonForSIGILL(info); + } + + assert(false && "unexpected signal"); + return CrashReason::eInvalidCrashReason; +} diff --git a/source/Plugins/Process/POSIX/CrashReason.h b/source/Plugins/Process/POSIX/CrashReason.h new file mode 100644 index 000000000000..f6d9ba553e4a --- /dev/null +++ b/source/Plugins/Process/POSIX/CrashReason.h @@ -0,0 +1,62 @@ +//===-- CrashReason.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CrashReason_H_ +#define liblldb_CrashReason_H_ + +#include "lldb/lldb-types.h" + +#include + +#include + +enum class CrashReason +{ + eInvalidCrashReason, + + // SIGSEGV crash reasons. + eInvalidAddress, + ePrivilegedAddress, + + // SIGILL crash reasons. + eIllegalOpcode, + eIllegalOperand, + eIllegalAddressingMode, + eIllegalTrap, + ePrivilegedOpcode, + ePrivilegedRegister, + eCoprocessorError, + eInternalStackError, + + // SIGBUS crash reasons, + eIllegalAlignment, + eIllegalAddress, + eHardwareError, + + // SIGFPE crash reasons, + eIntegerDivideByZero, + eIntegerOverflow, + eFloatDivideByZero, + eFloatOverflow, + eFloatUnderflow, + eFloatInexactResult, + eFloatInvalidOperation, + eFloatSubscriptRange +}; + +std::string +GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr); + +const char * +CrashReasonAsString (CrashReason reason); + +CrashReason +GetCrashReason(const siginfo_t& info); + +#endif // #ifndef liblldb_CrashReason_H_ diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp index 6e2c140682ba..3b8cea737bcb 100644 --- a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp +++ b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp @@ -45,6 +45,15 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) //===----------------------------------------------------------------------===// // POSIXCrashStopInfo +POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread, + uint32_t status, + CrashReason reason, + lldb::addr_t fault_addr) + : POSIXStopInfo(thread, status) +{ + m_description = ::GetCrashReasonString(reason, fault_addr); +} + POSIXCrashStopInfo::~POSIXCrashStopInfo() { } lldb::StopReason @@ -53,12 +62,6 @@ POSIXCrashStopInfo::GetStopReason() const return lldb::eStopReasonException; } -const char * -POSIXCrashStopInfo::GetDescription() -{ - return ProcessMessage::GetCrashReasonString(m_crash_reason, m_fault_addr); -} - //===----------------------------------------------------------------------===// // POSIXNewThreadStopInfo diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.h b/source/Plugins/Process/POSIX/POSIXStopInfo.h index cbf309e53506..a1ee2ea68524 100644 --- a/source/Plugins/Process/POSIX/POSIXStopInfo.h +++ b/source/Plugins/Process/POSIX/POSIXStopInfo.h @@ -16,8 +16,10 @@ // Project includes #include "lldb/Target/StopInfo.h" +#include "CrashReason.h" #include "POSIXThread.h" -#include "ProcessMessage.h" + +#include //===----------------------------------------------------------------------===// /// @class POSIXStopInfo @@ -69,25 +71,13 @@ class POSIXCrashStopInfo { public: POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, - ProcessMessage::CrashReason reason, - lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status), - m_crash_reason(reason), - m_fault_addr(fault_addr) - { } - + CrashReason reason, + lldb::addr_t fault_addr); ~POSIXCrashStopInfo(); lldb::StopReason GetStopReason() const; - - const char * - GetDescription(); - -private: - ProcessMessage::CrashReason m_crash_reason; - lldb::addr_t m_fault_addr; -}; +}; //===----------------------------------------------------------------------===// /// @class POSIXNewThreadStopInfo diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp index 5c53627f9e0b..02049a2af953 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -9,205 +9,19 @@ #include "ProcessMessage.h" -#include - using namespace lldb_private; -namespace { - -inline void AppendFaultAddr(std::string& str, lldb::addr_t addr) -{ - std::stringstream ss; - ss << " (fault address: 0x" << std::hex << addr << ")"; - str += ss.str(); -} - -} - -const char * -ProcessMessage::GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) -{ - static std::string str; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidAddress: - str = "invalid address"; - AppendFaultAddr(str, fault_addr); - break; - case ePrivilegedAddress: - str = "address access protected"; - AppendFaultAddr(str, fault_addr); - break; - case eIllegalOpcode: - str = "illegal instruction"; - break; - case eIllegalOperand: - str = "illegal instruction operand"; - break; - case eIllegalAddressingMode: - str = "illegal addressing mode"; - break; - case eIllegalTrap: - str = "illegal trap"; - break; - case ePrivilegedOpcode: - str = "privileged instruction"; - break; - case ePrivilegedRegister: - str = "privileged register"; - break; - case eCoprocessorError: - str = "coprocessor error"; - break; - case eInternalStackError: - str = "internal stack error"; - break; - case eIllegalAlignment: - str = "illegal alignment"; - break; - case eIllegalAddress: - str = "illegal address"; - break; - case eHardwareError: - str = "hardware error"; - break; - case eIntegerDivideByZero: - str = "integer divide by zero"; - break; - case eIntegerOverflow: - str = "integer overflow"; - break; - case eFloatDivideByZero: - str = "floating point divide by zero"; - break; - case eFloatOverflow: - str = "floating point overflow"; - break; - case eFloatUnderflow: - str = "floating point underflow"; - break; - case eFloatInexactResult: - str = "inexact floating point result"; - break; - case eFloatInvalidOperation: - str = "invalid floating point operation"; - break; - case eFloatSubscriptRange: - str = "invalid floating point subscript range"; - break; - } - - return str.c_str(); -} - -const char * -ProcessMessage::PrintCrashReason(CrashReason reason) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (reason) - { - case eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; - - // SIGSEGV crash reasons. - case eInvalidAddress: - str = "eInvalidAddress"; - break; - case ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; - - // SIGILL crash reasons. - case eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case eIllegalOperand: - str = "eIllegalOperand"; - break; - case eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case eIllegalTrap: - str = "eIllegalTrap"; - break; - case ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case eCoprocessorError: - str = "eCoprocessorError"; - break; - case eInternalStackError: - str = "eInternalStackError"; - break; - - // SIGBUS crash reasons: - case eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case eIllegalAddress: - str = "eIllegalAddress"; - break; - case eHardwareError: - str = "eHardwareError"; - break; - - // SIGFPE crash reasons: - case eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case eFloatOverflow: - str = "eFloatOverflow"; - break; - case eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } -#endif - - return str; -} - const char * ProcessMessage::PrintCrashReason() const { - return PrintCrashReason(m_crash_reason); + return CrashReasonAsString(m_crash_reason); } const char * ProcessMessage::PrintKind(Kind kind) { #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. + // Just return the code in ascii for integration builds. chcar str[8]; sprintf(str, "%d", reason); #else diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h index 40462d0f0e13..f932e9fff278 100644 --- a/source/Plugins/Process/POSIX/ProcessMessage.h +++ b/source/Plugins/Process/POSIX/ProcessMessage.h @@ -10,7 +10,10 @@ #ifndef liblldb_ProcessMessage_H_ #define liblldb_ProcessMessage_H_ +#include "CrashReason.h" + #include +#include #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" @@ -36,44 +39,10 @@ class ProcessMessage eExecMessage }; - enum CrashReason - { - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange - }; - ProcessMessage() : m_tid(LLDB_INVALID_PROCESS_ID), m_kind(eInvalidMessage), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), m_addr(0) { } @@ -175,15 +144,9 @@ class ProcessMessage return m_child_tid; } - static const char * - GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr); - const char * PrintCrashReason() const; - static const char * - PrintCrashReason(CrashReason reason); - const char * PrintKind() const; @@ -195,7 +158,7 @@ class ProcessMessage int status = 0, lldb::addr_t addr = 0) : m_tid(tid), m_kind(kind), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(status), m_addr(addr), m_child_tid(0) { } @@ -203,14 +166,14 @@ class ProcessMessage ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid) : m_tid(tid), m_kind(kind), - m_crash_reason(eInvalidCrashReason), + m_crash_reason(CrashReason::eInvalidCrashReason), m_status(0), m_addr(0), m_child_tid(child_tid) { } lldb::tid_t m_tid; Kind m_kind : 8; - CrashReason m_crash_reason : 8; + CrashReason m_crash_reason; int m_status; lldb::addr_t m_addr; lldb::tid_t m_child_tid; diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index 0e5ab5a8d8b1..882fac75c9a0 100644 --- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -252,7 +252,16 @@ ProcessPOSIX::DoLaunch (Module *module, if (!error.Success()) return error; - SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); + int terminal = m_monitor->GetTerminalFD(); + if (terminal >= 0) { + // The reader thread will close the file descriptor when done, so we pass it a copy. + int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); + if (stdio == -1) { + error.SetErrorToErrno(); + return error; + } + SetSTDIOFileDescriptor(stdio); + } SetID(m_monitor->GetPID()); return error; diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp index b542db4779db..80e1c1984225 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -38,14 +38,21 @@ RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() { - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize()); } bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() { - // XXX not yet implemented + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() +{ + // XXX: Need a way to read/write process VMX registers with ptrace. return false; } @@ -59,7 +66,14 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() { - // XXX not yet implemented + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc, sizeof(m_fpr_powerpc)); +} + +bool +RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() +{ + // XXX: Need a way to read/write process VMX registers with ptrace. return false; } @@ -146,26 +160,15 @@ RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg { if (!ReadFPR()) return false; + uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + value.SetUInt64(*(uint64_t*)src); } - else + else if (IsGPR(reg)) { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) - { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - bool success = ReadRegister(full_reg, value); + bool success = ReadRegister(reg, value); if (success) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - value.SetUInt64(value.GetAsUInt64() >> 8); - // If our return byte size was greater than the return value reg size, then // use the type specified by reg_info rather than the uint64_t default if (value.GetByteSize() > reg_info->byte_size) @@ -183,7 +186,16 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *re const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; if (IsGPR(reg)) + { return WriteRegister(reg, value); + } + else if (IsFPR(reg)) + { + assert (reg_info->byte_offset < sizeof(m_fpr_powerpc)); + uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset; + *(uint64_t *)dst = value.GetAsUInt64(); + return WriteFPR(); + } return false; } @@ -221,6 +233,9 @@ RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBuf if (WriteGPR()) { src += GetGPRSize(); + ::memcpy (&m_fpr_powerpc, src, sizeof(m_fpr_powerpc)); + + success = WriteFPR(); } } } diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h index 92a331285515..5c686df4836f 100644 --- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h +++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -22,18 +22,27 @@ class RegisterContextPOSIXProcessMonitor_powerpc: lldb_private::RegisterInfoInterface *register_info); protected: + bool + IsVMX(); + bool ReadGPR(); bool ReadFPR(); + bool + ReadVMX(); + bool WriteGPR(); bool WriteFPR(); + bool + WriteVMX(); + // lldb_private::RegisterContext bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value); diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1088924bfeac..25a195e11a03 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -15,7 +15,7 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/FormatManager.h" @@ -158,8 +158,8 @@ DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict regex_match.GetMatchAtIndex(slice_cstr, 2, msbit_str) && regex_match.GetMatchAtIndex(slice_cstr, 3, lsbit_str)) { - const uint32_t msbit = Args::StringToUInt32(msbit_str.c_str(), UINT32_MAX); - const uint32_t lsbit = Args::StringToUInt32(lsbit_str.c_str(), UINT32_MAX); + const uint32_t msbit = StringConvert::ToUInt32(msbit_str.c_str(), UINT32_MAX); + const uint32_t lsbit = StringConvert::ToUInt32(lsbit_str.c_str(), UINT32_MAX); if (msbit != UINT32_MAX && lsbit != UINT32_MAX) { if (msbit > lsbit) diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 5170e6d2accb..5133d6088bd3 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -134,6 +134,45 @@ typedef struct _FPR uint64_t fpscr; } FPR; +typedef struct _VMX +{ + uint32_t v0[4]; + uint32_t v1[4]; + uint32_t v2[4]; + uint32_t v3[4]; + uint32_t v4[4]; + uint32_t v5[4]; + uint32_t v6[4]; + uint32_t v7[4]; + uint32_t v8[4]; + uint32_t v9[4]; + uint32_t v10[4]; + uint32_t v11[4]; + uint32_t v12[4]; + uint32_t v13[4]; + uint32_t v14[4]; + uint32_t v15[4]; + uint32_t v16[4]; + uint32_t v17[4]; + uint32_t v18[4]; + uint32_t v19[4]; + uint32_t v20[4]; + uint32_t v21[4]; + uint32_t v22[4]; + uint32_t v23[4]; + uint32_t v24[4]; + uint32_t v25[4]; + uint32_t v26[4]; + uint32_t v27[4]; + uint32_t v28[4]; + uint32_t v29[4]; + uint32_t v30[4]; + uint32_t v31[4]; + uint32_t pad[2]; + uint32_t vrsave; + uint32_t vscr; +} VMX; + //--------------------------------------------------------------------------- // Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure. //--------------------------------------------------------------------------- diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index f47d687702ec..1b3a9491d1c8 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -811,7 +811,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () if (m_frame_type == eTrapHandlerFrame && process) { m_fast_unwind_plan_sp.reset(); - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc) && unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes) { return unwind_plan_sp; @@ -826,7 +826,10 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // But there is not. if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx)) { - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (process->GetTarget(), m_current_offset_backed_up_one); + // We must specifically call the GetEHFrameUnwindPlan() method here -- normally we would + // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind plan sourced from + // either eh_frame (that's what we intend) or compact unwind (this won't work) + unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index b9b9dca07be4..b38d6cc60cac 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -125,3 +125,8 @@ RegisterContextLinux_i386::GetRegisterCount () const return static_cast (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0])); } +uint32_t +RegisterContextLinux_i386::GetUserRegisterCount () const +{ + return static_cast (k_num_user_registers_i386); +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index f8b21fc8e87d..cb71d7993e17 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -26,6 +26,9 @@ class RegisterContextLinux_i386 uint32_t GetRegisterCount () const override; + + uint32_t + GetUserRegisterCount () const override; }; #endif diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index 74f016bd744d..5c93ebf88faa 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -145,10 +145,26 @@ GetRegisterInfoCount (const ArchSpec &target_arch) } } +static uint32_t +GetUserRegisterInfoCount (const ArchSpec &target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::x86: + return static_cast (k_num_user_registers_i386); + case llvm::Triple::x86_64: + return static_cast (k_num_user_registers_x86_64); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) : lldb_private::RegisterInfoInterface(target_arch), m_register_info_p (GetRegisterInfoPtr (target_arch)), - m_register_info_count (GetRegisterInfoCount (target_arch)) + m_register_info_count (GetRegisterInfoCount (target_arch)), + m_user_register_count (GetUserRegisterInfoCount (target_arch)) { } @@ -169,3 +185,9 @@ RegisterContextLinux_x86_64::GetRegisterCount () const { return m_register_info_count; } + +uint32_t +RegisterContextLinux_x86_64::GetUserRegisterCount () const +{ + return m_user_register_count; +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index 7b6828661c1e..0cdfae9ac943 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -27,9 +27,13 @@ class RegisterContextLinux_x86_64 uint32_t GetRegisterCount () const override; + uint32_t + GetUserRegisterCount () const override; + private: const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; + uint32_t m_user_register_count; }; #endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index a9477d583517..828fb2571f79 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -106,10 +106,49 @@ uint32_t g_fpr_regnums[] = fpr_fpscr_powerpc, }; +static const +uint32_t g_vmx_regnums[] = +{ + vmx_v0_powerpc, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, +}; + // Number of register sets provided by this context. enum { - k_num_register_sets = 2 + k_num_register_sets = 3 }; static const RegisterSet @@ -117,20 +156,26 @@ g_reg_sets_powerpc[k_num_register_sets] = { { "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums }, { "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums }, + { "Altivec/VMX Registers", "vmx", k_num_vmx_registers_powerpc, g_vmx_regnums }, }; bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg) { - return reg <= k_num_gpr_registers_powerpc; // GPR's come first. + return (reg >= k_first_gpr_powerpc) && (reg <= k_last_gpr_powerpc); // GPR's come first. } bool RegisterContextPOSIX_powerpc::IsFPR(unsigned reg) { - // XXX return (reg >= k_first_fpr) && (reg <= k_last_fpr); } +bool +RegisterContextPOSIX_powerpc::IsVMX(unsigned reg) +{ + return (reg >= k_first_vmx) && (reg <= k_last_vmx); +} + RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread, uint32_t concrete_frame_idx, RegisterInfoInterface *register_info) diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index 3194c3968c98..c7a2451d7811 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -97,9 +97,47 @@ enum fpr_fpscr_powerpc, k_last_fpr = fpr_fpscr_powerpc, + k_first_vmx, + vmx_v0_powerpc = k_first_vmx, + vmx_v1_powerpc, + vmx_v2_powerpc, + vmx_v3_powerpc, + vmx_v4_powerpc, + vmx_v5_powerpc, + vmx_v6_powerpc, + vmx_v7_powerpc, + vmx_v8_powerpc, + vmx_v9_powerpc, + vmx_v10_powerpc, + vmx_v11_powerpc, + vmx_v12_powerpc, + vmx_v13_powerpc, + vmx_v14_powerpc, + vmx_v15_powerpc, + vmx_v16_powerpc, + vmx_v17_powerpc, + vmx_v18_powerpc, + vmx_v19_powerpc, + vmx_v20_powerpc, + vmx_v21_powerpc, + vmx_v22_powerpc, + vmx_v23_powerpc, + vmx_v24_powerpc, + vmx_v25_powerpc, + vmx_v26_powerpc, + vmx_v27_powerpc, + vmx_v28_powerpc, + vmx_v29_powerpc, + vmx_v30_powerpc, + vmx_v31_powerpc, + vmx_vrsave_powerpc, + vmx_vscr_powerpc, + k_last_vmx = vmx_vscr_powerpc, + k_num_registers_powerpc, k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1, k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1, + k_num_vmx_registers_powerpc = k_last_vmx - k_first_vmx + 1, }; class RegisterContextPOSIX_powerpc @@ -147,6 +185,8 @@ class RegisterContextPOSIX_powerpc protected: uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers. + uint64_t m_fpr_powerpc[k_num_fpr_registers_powerpc]; // floating point registers. + uint32_t m_vmx_powerpc[k_num_vmx_registers_powerpc][4]; std::unique_ptr m_register_info_ap; // Register Info Interface (FreeBSD or Linux) // Determines if an extended register set is supported on the processor running the inferior process. @@ -162,12 +202,17 @@ class RegisterContextPOSIX_powerpc bool IsFPR(unsigned reg); + bool + IsVMX(unsigned reg); + lldb::ByteOrder GetByteOrder(); virtual bool ReadGPR() = 0; virtual bool ReadFPR() = 0; + virtual bool ReadVMX() = 0; virtual bool WriteGPR() = 0; virtual bool WriteFPR() = 0; + virtual bool WriteVMX() = 0; }; #endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h index cf54cc0c2145..7438b88971b3 100644 --- a/source/Plugins/Process/Utility/RegisterContext_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -79,10 +79,45 @@ enum gcc_dwarf_f31_powerpc, gcc_dwarf_cr_powerpc, gcc_dwarf_fpscr_powerpc, + gcc_dwarf_msr_powerpc, + gcc_dwarf_vscr_powerpc, gcc_dwarf_xer_powerpc = 101, gcc_dwarf_lr_powerpc = 108, gcc_dwarf_ctr_powerpc, gcc_dwarf_pc_powerpc, + gcc_dwarf_vrsave_powerpc = 356, + gcc_dwarf_v0_powerpc = 1124, + gcc_dwarf_v1_powerpc, + gcc_dwarf_v2_powerpc, + gcc_dwarf_v3_powerpc, + gcc_dwarf_v4_powerpc, + gcc_dwarf_v5_powerpc, + gcc_dwarf_v6_powerpc, + gcc_dwarf_v7_powerpc, + gcc_dwarf_v8_powerpc, + gcc_dwarf_v9_powerpc, + gcc_dwarf_v10_powerpc, + gcc_dwarf_v11_powerpc, + gcc_dwarf_v12_powerpc, + gcc_dwarf_v13_powerpc, + gcc_dwarf_v14_powerpc, + gcc_dwarf_v15_powerpc, + gcc_dwarf_v16_powerpc, + gcc_dwarf_v17_powerpc, + gcc_dwarf_v18_powerpc, + gcc_dwarf_v19_powerpc, + gcc_dwarf_v20_powerpc, + gcc_dwarf_v21_powerpc, + gcc_dwarf_v22_powerpc, + gcc_dwarf_v23_powerpc, + gcc_dwarf_v24_powerpc, + gcc_dwarf_v25_powerpc, + gcc_dwarf_v26_powerpc, + gcc_dwarf_v27_powerpc, + gcc_dwarf_v28_powerpc, + gcc_dwarf_v29_powerpc, + gcc_dwarf_v30_powerpc, + gcc_dwarf_v31_powerpc, }; // GDB Register numbers (eRegisterKindGDB) @@ -152,12 +187,46 @@ enum gdb_f29_powerpc, gdb_f30_powerpc, gdb_f31_powerpc, - gdb_cr_powerpc, - gdb_fpscr_powerpc, - gdb_xer_powerpc = 101, - gdb_lr_powerpc = 108, - gdb_ctr_powerpc, gdb_pc_powerpc, + gdb_cr_powerpc = 66, + gdb_lr_powerpc, + gdb_ctr_powerpc, + gdb_xer_powerpc, + gdb_fpscr_powerpc, + gdb_v0_powerpc = 106, + gdb_v1_powerpc, + gdb_v2_powerpc, + gdb_v3_powerpc, + gdb_v4_powerpc, + gdb_v5_powerpc, + gdb_v6_powerpc, + gdb_v7_powerpc, + gdb_v8_powerpc, + gdb_v9_powerpc, + gdb_v10_powerpc, + gdb_v11_powerpc, + gdb_v12_powerpc, + gdb_v13_powerpc, + gdb_v14_powerpc, + gdb_v15_powerpc, + gdb_v16_powerpc, + gdb_v17_powerpc, + gdb_v18_powerpc, + gdb_v19_powerpc, + gdb_v20_powerpc, + gdb_v21_powerpc, + gdb_v22_powerpc, + gdb_v23_powerpc, + gdb_v24_powerpc, + gdb_v25_powerpc, + gdb_v26_powerpc, + gdb_v27_powerpc, + gdb_v28_powerpc, + gdb_v29_powerpc, + gdb_v30_powerpc, + gdb_v31_powerpc, + gdb_vscr_powerpc, + gdb_vrsave_powerpc, }; #endif // liblldb_RegisterContext_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 382475f4523a..94cb5cc791c6 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -32,9 +32,20 @@ namespace lldb_private virtual const lldb_private::RegisterInfo * GetRegisterInfo () const = 0; + // Returns the number of registers including the user registers and the + // lldb internal registers also virtual uint32_t GetRegisterCount () const = 0; + // Returns the number of the user registers (excluding the registers + // kept for lldb internal use only). Subclasses should override it if + // they belongs to an architecture with lldb internal registers. + virtual uint32_t + GetUserRegisterCount () const + { + return GetRegisterCount(); + } + const lldb_private::ArchSpec& GetTargetArchitecture() const { return m_target_arch; } diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h index 045426648105..fe145e99588b 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -14,6 +14,8 @@ (offsetof(GPR, regname)) #define FPR_OFFSET(regname) \ (offsetof(FPR, regname)) +#define VMX_OFFSET(regname) \ + (offsetof(VMX, regname)) #define GPR_SIZE(regname) \ (sizeof(((GPR*)NULL)->regname)) @@ -26,6 +28,9 @@ #define DEFINE_FPR(reg, lldb_kind) \ { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \ eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL } +#define DEFINE_VMX(reg, lldb_kind) \ + { #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \ + eFormatVectorOfUInt32, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, vmx_##reg##_powerpc }, NULL, NULL } // General purpose registers. GCC, DWARF, Generic, GDB #define POWERPC_REGS \ @@ -98,7 +103,42 @@ DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \ DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \ DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \ - { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, + { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, \ + DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v3, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v4, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v5, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v6, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v7, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v8, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v9, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v10, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v11, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v12, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v13, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v14, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v15, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v16, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v17, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v18, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v19, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v20, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v21, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v22, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v23, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v24, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v25, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v26, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v27, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v28, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \ + { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { gcc_dwarf_vrsave_powerpc, gcc_dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, gdb_vrsave_powerpc, vmx_vrsave_powerpc }, NULL, NULL }, \ + { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { gcc_dwarf_vscr_powerpc, gcc_dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, gdb_vscr_powerpc, vmx_vscr_powerpc }, NULL, NULL }, + static RegisterInfo g_register_infos_powerpc64[] = { diff --git a/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/source/Plugins/Process/Utility/lldb-x86-register-enums.h index 99fca3005820..63027b4451b8 100644 --- a/source/Plugins/Process/Utility/lldb-x86-register-enums.h +++ b/source/Plugins/Process/Utility/lldb-x86-register-enums.h @@ -118,7 +118,8 @@ namespace lldb_private k_num_registers_i386, k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1, k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1, - k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1 + k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1, + k_num_user_registers_i386 = k_num_gpr_registers_i386 + k_num_fpr_registers_i386 + k_num_avx_registers_i386, }; //--------------------------------------------------------------------------- @@ -285,7 +286,8 @@ namespace lldb_private k_num_registers_x86_64, k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1, k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1, - k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1 + k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1, + k_num_user_registers_x86_64 = k_num_gpr_registers_x86_64 + k_num_fpr_registers_x86_64 + k_num_avx_registers_x86_64, }; } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index fb39d7318a5a..ead959508d88 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -412,7 +412,8 @@ enum { NT_FPREGSET, NT_PRPSINFO, NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16 + NT_PROCSTAT_AUXV = 16, + NT_PPC_VMX = 0x100 }; } @@ -538,6 +539,9 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * // FIXME: FreeBSD sticks an int at the beginning of the note m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); break; + case FREEBSD::NT_PPC_VMX: + thread_data->vregset = note_data; + break; default: break; } diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index 15b1b44182d7..d12df21a8664 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -18,7 +18,8 @@ using namespace lldb_private; RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread, RegisterInfoInterface *register_info, const DataExtractor &gpregset, - const DataExtractor &fpregset) + const DataExtractor &fpregset, + const DataExtractor &vregset) : RegisterContextPOSIX_powerpc(thread, 0, register_info) { m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); @@ -27,6 +28,9 @@ RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &threa m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); m_fpr.SetByteOrder(fpregset.GetByteOrder()); + m_vec_buffer.reset(new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); + m_vec.SetData(m_vec_buffer); + m_vec.SetByteOrder(fpregset.GetByteOrder()); } RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() @@ -45,6 +49,12 @@ RegisterContextCorePOSIX_powerpc::ReadFPR() return true; } +bool +RegisterContextCorePOSIX_powerpc::ReadVMX() +{ + return true; +} + bool RegisterContextCorePOSIX_powerpc::WriteGPR() { @@ -59,17 +69,32 @@ RegisterContextCorePOSIX_powerpc::WriteFPR() return false; } +bool +RegisterContextCorePOSIX_powerpc::WriteVMX() +{ + assert(0); + return false; +} + bool RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) { lldb::offset_t offset = reg_info->byte_offset; - if (reg_info->name[0] == 'f') { + if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) { value = v; return true; } + } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + offset = m_vec.CopyData(offset, reg_info->byte_size, &v); + if (offset == reg_info->byte_size) + { + value.SetBytes(v, reg_info->byte_size, m_vec.GetByteOrder()); + return true; + } } else { uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index e6575581b360..a3590601fa7e 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -20,7 +20,8 @@ class RegisterContextCorePOSIX_powerpc : RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + const lldb_private::DataExtractor &fpregset, + const lldb_private::DataExtractor &vregset); ~RegisterContextCorePOSIX_powerpc(); @@ -46,17 +47,25 @@ class RegisterContextCorePOSIX_powerpc : bool ReadFPR(); + bool + ReadVMX(); + bool WriteGPR(); bool WriteFPR(); + bool + WriteVMX(); + private: lldb::DataBufferSP m_gpr_buffer; lldb::DataBufferSP m_fpr_buffer; + lldb::DataBufferSP m_vec_buffer; lldb_private::DataExtractor m_gpr; lldb_private::DataExtractor m_fpr; + lldb_private::DataExtractor m_vec; }; #endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index d62bcfcff600..b16335fb8e1e 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -38,7 +38,8 @@ ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, m_thread_reg_ctx_sp (), m_signo(td.signo), m_gpregset_data(td.gpregset), - m_fpregset_data(td.fpregset) + m_fpregset_data(td.fpregset), + m_vregset_data(td.vregset) { } @@ -148,7 +149,7 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data)); + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data)); break; case llvm::Triple::x86: case llvm::Triple::x86_64: diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index f1f00cf019b3..50502c101daf 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -111,6 +111,7 @@ struct ThreadData { lldb_private::DataExtractor gpregset; lldb_private::DataExtractor fpregset; + lldb_private::DataExtractor vregset; int signo; std::string name; }; @@ -170,6 +171,7 @@ class ThreadElfCore : public lldb_private::Thread lldb_private::DataExtractor m_gpregset_data; lldb_private::DataExtractor m_fpregset_data; + lldb_private::DataExtractor m_vregset_data; virtual bool CalculateStopInfo(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 919fa5405117..d633b3eaf34c 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -26,9 +26,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" +#include "llvm/ADT/SmallString.h" // Project includes #include "ProcessGDBRemoteLog.h" @@ -756,13 +758,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } // use native registers, not the GDB registers - debugserver_args.AppendArgument("--native-regs"); - // make debugserver run in its own session so signals generated by - // special terminal key sequences (^C) don't affect debugserver - debugserver_args.AppendArgument("--setsid"); + debugserver_args.AppendArgument("--native-regs"); - char named_pipe_path[PATH_MAX]; - named_pipe_path[0] = '\0'; + if (launch_info.GetLaunchInSeparateProcessGroup()) + { + debugserver_args.AppendArgument("--setsid"); + } + + llvm::SmallString named_pipe_path; Pipe port_named_pipe; bool listen = false; @@ -776,25 +779,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, { // Binding to port zero, we need to figure out what port it ends up // using using a named pipe... - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("debugserver-named-pipe.XXXXXX"); - strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path)); - } - else - { - strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path)); - } - - if (::mktemp (named_pipe_path)) - { - error = port_named_pipe.CreateNew(named_pipe_path, false); - if (error.Fail()) - return error; - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path); - } + error = port_named_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); + if (error.Fail()) + return error; + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path.c_str()); } else { @@ -874,7 +863,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { - if (named_pipe_path[0]) + if (named_pipe_path.size() > 0) { error = port_named_pipe.OpenAsReader(named_pipe_path, false); if (error.Success()) @@ -887,14 +876,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (error.Success()) { assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = Args::StringToUInt32(port_cstr, 0); + out_port = StringConvert::ToUInt32(port_cstr, 0); if (log) log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port); } else { if (log) - log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } port_named_pipe.Close(); @@ -902,13 +891,13 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, else { if (log) - log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path.c_str(), error.AsCString()); } const auto err = port_named_pipe.Delete(named_pipe_path); if (err.Fail()) { if (log) - log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString()); + log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path.c_str(), err.AsCString()); } } else if (listen) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index ac203a62788a..ee2f3276513d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -27,6 +27,16 @@ #include "Utility/StringExtractorGDBRemote.h" +typedef enum +{ + eStoppointInvalid = -1, + eBreakpointSoftware = 0, + eBreakpointHardware, + eWatchpointWrite, + eWatchpointRead, + eWatchpointReadWrite +} GDBStoppointType; + class ProcessGDBRemote; class GDBRemoteCommunication : public lldb_private::Communication @@ -282,9 +292,8 @@ class GDBRemoteCommunication : public lldb_private::Communication ListenThread (lldb::thread_arg_t arg); private: - lldb_private::HostThread m_listen_thread; + lldb_private::HostThread m_listen_thread; std::string m_listen_url; - //------------------------------------------------------------------ // For GDBRemoteCommunication only diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 52750de5a25f..0f99688fc823 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -28,6 +28,7 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Target.h" @@ -1210,13 +1211,13 @@ GDBRemoteCommunicationClient::SendInterrupt } lldb::pid_t -GDBRemoteCommunicationClient::GetCurrentProcessID () +GDBRemoteCommunicationClient::GetCurrentProcessID (bool allow_lazy) { - if (m_curr_pid_is_valid == eLazyBoolYes) + if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) return m_curr_pid; // First try to retrieve the pid via the qProcessInfo request. - GetCurrentProcessInfo (); + GetCurrentProcessInfo (allow_lazy); if (m_curr_pid_is_valid == eLazyBoolYes) { // We really got it. @@ -1559,7 +1560,7 @@ GDBRemoteCommunicationClient::GetGDBServerVersion() size_t dot_pos = value.find('.'); if (dot_pos != std::string::npos) value[dot_pos] = '\0'; - const uint32_t version = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0); + const uint32_t version = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0); if (version != UINT32_MAX) { success = true; @@ -1625,14 +1626,14 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) if (name.compare("cputype") == 0) { // exception type in big endian hex - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); if (cpu != LLDB_INVALID_CPUTYPE) ++num_keys_decoded; } else if (name.compare("cpusubtype") == 0) { // exception count in big endian hex - sub = Args::StringToUInt32 (value.c_str(), 0, 0); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 0); if (sub != 0) ++num_keys_decoded; } @@ -1700,7 +1701,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("ptrsize") == 0) { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); + pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 0); if (pointer_byte_size != 0) ++num_keys_decoded; } @@ -1725,7 +1726,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("default_packet_timeout") == 0) { - m_default_packet_timeout = Args::StringToUInt32(value.c_str(), 0); + m_default_packet_timeout = StringConvert::ToUInt32(value.c_str(), 0); if (m_default_packet_timeout > 0) { SetPacketTimeout(m_default_packet_timeout); @@ -1865,6 +1866,21 @@ GDBRemoteCommunicationClient::SendAttach return -1; } +int +GDBRemoteCommunicationClient::SendStdinNotification (const char* data, size_t data_len) +{ + StreamString packet; + packet.PutCString("I"); + packet.PutBytesAsRawHex8(data, data_len); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success) + { + return 0; + } + return response.GetError(); + +} + const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture () { @@ -2006,13 +2022,13 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, { if (name.compare ("start") == 0) { - addr_value = Args::StringToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); + addr_value = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success); if (success) region_info.GetRange().SetRangeBase(addr_value); } else if (name.compare ("size") == 0) { - addr_value = Args::StringToUInt64(value.c_str(), 0, 16, &success); + addr_value = StringConvert::ToUInt64(value.c_str(), 0, 16, &success); if (success) region_info.GetRange().SetByteSize (addr_value); } @@ -2107,7 +2123,7 @@ GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num) { if (name.compare ("num") == 0) { - num = Args::StringToUInt32(value.c_str(), 0, 0); + num = StringConvert::ToUInt32(value.c_str(), 0, 0); m_num_supported_hardware_watchpoints = num; } } @@ -2309,27 +2325,27 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot { if (name.compare("pid") == 0) { - process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + process_info.SetProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); } else if (name.compare("ppid") == 0) { - process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + process_info.SetParentProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); } else if (name.compare("uid") == 0) { - process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("euid") == 0) { - process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetEffectiveUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("gid") == 0) { - process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("egid") == 0) { - process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + process_info.SetEffectiveGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0)); } else if (name.compare("triple") == 0) { @@ -2351,11 +2367,11 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot } else if (name.compare("cputype") == 0) { - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); } else if (name.compare("cpusubtype") == 0) { - sub = Args::StringToUInt32 (value.c_str(), 0, 16); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 16); } else if (name.compare("vendor") == 0) { @@ -2408,14 +2424,17 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn } bool -GDBRemoteCommunicationClient::GetCurrentProcessInfo () +GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) { Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); - if (m_qProcessInfo_is_valid == eLazyBoolYes) - return true; - if (m_qProcessInfo_is_valid == eLazyBoolNo) - return false; + if (allow_lazy) + { + if (m_qProcessInfo_is_valid == eLazyBoolYes) + return true; + if (m_qProcessInfo_is_valid == eLazyBoolNo) + return false; + } GetHostInfo (); @@ -2441,13 +2460,13 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () { if (name.compare("cputype") == 0) { - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); if (cpu != LLDB_INVALID_CPUTYPE) ++num_keys_decoded; } else if (name.compare("cpusubtype") == 0) { - sub = Args::StringToUInt32 (value.c_str(), 0, 16); + sub = StringConvert::ToUInt32 (value.c_str(), 0, 16); if (sub != 0) ++num_keys_decoded; } @@ -2483,13 +2502,13 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("ptrsize") == 0) { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 16); + pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 16); if (pointer_byte_size != 0) ++num_keys_decoded; } else if (name.compare("pid") == 0) { - pid = Args::StringToUInt64(value.c_str(), 0, 16); + pid = StringConvert::ToUInt64(value.c_str(), 0, 16); if (pid != LLDB_INVALID_PROCESS_ID) ++num_keys_decoded; } @@ -2849,7 +2868,11 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const const char *packet = stream.GetData(); int packet_len = stream.GetSize(); - if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success) + // give the process a few seconds to startup + const uint32_t old_packet_timeout = SetPacketTimeout (10); + auto result = SendPacketAndWaitForResponse(packet, packet_len, response, false); + SetPacketTimeout (old_packet_timeout); + if (result == PacketResult::Success) { std::string name; std::string value; @@ -2857,9 +2880,9 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const while (response.GetNameColonValue(name, value)) { if (name.compare("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); + port = StringConvert::ToUInt32(value.c_str(), 0, 0); else if (name.compare("pid") == 0) - pid = Args::StringToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); + pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); } return port; } @@ -3013,6 +3036,7 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, case eWatchpointWrite: m_supports_z2 = false; break; case eWatchpointRead: m_supports_z3 = false; break; case eWatchpointReadWrite: m_supports_z4 = false; break; + case eStoppointInvalid: return UINT8_MAX; } } } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index fddcd6cd1426..d90614bce88b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -21,15 +21,6 @@ #include "GDBRemoteCommunication.h" -typedef enum -{ - eBreakpointSoftware = 0, - eBreakpointHardware, - eWatchpointWrite, - eWatchpointRead, - eWatchpointReadWrite -} GDBStoppointType; - class GDBRemoteCommunicationClient : public GDBRemoteCommunication { public: @@ -109,7 +100,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteCommunication bool &timed_out); lldb::pid_t - GetCurrentProcessID (); + GetCurrentProcessID (bool allow_lazy = true); bool GetLaunchSuccess (std::string &error_str); @@ -183,6 +174,23 @@ class GDBRemoteCommunicationClient : public GDBRemoteCommunication StringExtractorGDBRemote& response); + //------------------------------------------------------------------ + /// Sends a GDB remote protocol 'I' packet that delivers stdin + /// data to the remote process. + /// + /// @param[in] data + /// A pointer to stdin data. + /// + /// @param[in] data_len + /// The number of bytes available at \a data. + /// + /// @return + /// Zero if the attach was successful, or an error indicating + /// an error code. + //------------------------------------------------------------------ + int + SendStdinNotification(const char* data, size_t data_len); + //------------------------------------------------------------------ /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. @@ -375,8 +383,8 @@ class GDBRemoteCommunicationClient : public GDBRemoteCommunication case eWatchpointWrite: return m_supports_z2; case eWatchpointRead: return m_supports_z3; case eWatchpointReadWrite: return m_supports_z4; + case eStoppointInvalid: return false; } - return false; } uint8_t SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint @@ -534,7 +542,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteCommunication StringExtractorGDBRemote &response); bool - GetCurrentProcessInfo (); + GetCurrentProcessInfo (bool allow_lazy_pid = true); bool GetGDBServerVersion(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index a7149505e869..dd920c0df0ca 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -34,16 +34,18 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" -#include "lldb/Target/NativeRegisterContext.h" -#include "Host/common/NativeProcessProtocol.h" -#include "Host/common/NativeThreadProtocol.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" +#include "Utility/UriParser.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" @@ -276,6 +278,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_qPlatform_shell (packet); break; + case StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo: + packet_result = Handle_qWatchpointSupportInfo (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_C: packet_result = Handle_C (packet); break; @@ -364,6 +370,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, packet_result = Handle_H (packet); break; + case StringExtractorGDBRemote::eServerPacketType_I: + packet_result = Handle_I (packet); + break; + case StringExtractorGDBRemote::eServerPacketType_m: packet_result = Handle_m (packet); break; @@ -601,14 +611,12 @@ GDBRemoteCommunicationServer::LaunchPlatformProcess () // add to list of spawned processes. On an lldb-gdbserver, we // would expect there to be only one. - lldb::pid_t pid; - if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID ) + const auto pid = m_process_launch_info.GetProcessID(); + if (pid != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - { - Mutex::Locker locker (m_spawned_pids_mutex); - m_spawned_pids.insert(pid); - } + Mutex::Locker locker (m_spawned_pids_mutex); + m_spawned_pids.insert(pid); } return error; @@ -835,12 +843,12 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; - if (!thread_sp->GetStopReason (tid_stop_info)) + std::string description; + if (!thread_sp->GetStopReason (tid_stop_info, description)) return SendErrorResponse (52); - const bool did_exec = tid_stop_info.reason == eStopReasonExec; // FIXME implement register handling for exec'd inferiors. - // if (did_exec) + // if (tid_stop_info.reason == eStopReasonExec) // { // const bool force = true; // InitializeRegisters(force); @@ -861,25 +869,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) tid_stop_info.details.exception.type); } - switch (tid_stop_info.reason) - { - case eStopReasonSignal: - case eStopReasonException: - signum = thread_sp->TranslateStopInfoToGdbSignal (tid_stop_info); - break; - default: - signum = 0; - if (log) - { - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " tid %" PRIu64 " has stop reason %d, using signo = 0 in stop reply response", - __FUNCTION__, - m_debugged_process_sp->GetID (), - tid, - tid_stop_info.reason); - } - break; - } - // Print the signal number. response.PutHex8 (signum & 0xff); @@ -906,14 +895,6 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) response.PutChar (';'); } - // FIXME look for analog - // thread_identifier_info_data_t thread_ident_info; - // if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info)) - // { - // if (thread_ident_info.dispatch_qaddr != 0) - // ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';'; - // } - // If a 'QListThreadsInStopReply' was sent to enable this feature, we // will send all thread IDs back in the "threads" key whose value is // a list of hex thread IDs separated by commas: @@ -978,9 +959,45 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) } } - if (did_exec) + const char* reason_str = nullptr; + switch (tid_stop_info.reason) { - response.PutCString ("reason:exec;"); + case eStopReasonTrace: + reason_str = "trace"; + break; + case eStopReasonBreakpoint: + reason_str = "breakpoint"; + break; + case eStopReasonWatchpoint: + reason_str = "watchpoint"; + break; + case eStopReasonSignal: + reason_str = "signal"; + break; + case eStopReasonException: + reason_str = "exception"; + break; + case eStopReasonExec: + reason_str = "exec"; + break; + case eStopReasonInstrumentation: + case eStopReasonInvalid: + case eStopReasonPlanComplete: + case eStopReasonThreadExiting: + case eStopReasonNone: + break; + } + if (reason_str != nullptr) + { + response.Printf ("reason:%s;", reason_str); + } + + if (!description.empty()) + { + // Description may contains special chars, send as hex bytes. + response.PutCString ("description:"); + response.PutCStringAsRawHex8 (description.c_str ()); + response.PutChar (';'); } else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { @@ -1422,23 +1439,34 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_qProcessInfo (StringExtractorGDBRemote &packet) { - // Only the gdb server handles this. - if (!IsGdbServer ()) - return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); - - // Fail if we don't have a current process. - if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse (68); - - ProcessInstanceInfo proc_info; - if (Host::GetProcessInfo (m_debugged_process_sp->GetID (), proc_info)) + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + if (IsGdbServer ()) { - StreamString response; - CreateProcessInfoResponse_DebugServerStyle(proc_info, response); - return SendPacketNoLock (response.GetData (), response.GetSize ()); + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse (68); + + pid = m_debugged_process_sp->GetID (); } - - return SendErrorResponse (1); + else if (m_is_platform) + { + pid = m_process_launch_info.GetProcessID (); + m_process_launch_info.Clear (); + } + else + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (1); + + ProcessInstanceInfo proc_info; + if (!Host::GetProcessInfo (pid, proc_info)) + return SendErrorResponse (1); + + StreamString response; + CreateProcessInfoResponse_DebugServerStyle(proc_info, response); + return SendPacketNoLock (response.GetData (), response.GetSize ()); } GDBRemoteCommunication::PacketResult @@ -1512,27 +1540,27 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa } else if (key.compare("pid") == 0) { - match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); } else if (key.compare("parent_pid") == 0) { - match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); } else if (key.compare("uid") == 0) { - match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("gid") == 0) { - match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("euid") == 0) { - match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("egid") == 0) { - match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success)); } else if (key.compare("all_users") == 0) { @@ -1627,7 +1655,7 @@ GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packe bool success = packet.GetNameColonValue(key, value); if (success && key.compare("response_size") == 0) { - uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); + uint32_t response_size = StringConvert::ToUInt32(value.c_str(), 0, 0, &success); if (success) { if (response_size == 0) @@ -1901,7 +1929,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote if (name.compare ("host") == 0) hostname.swap(value); else if (name.compare ("port") == 0) - port = Args::StringToUInt32(value.c_str(), 0, 0); + port = StringConvert::ToUInt32(value.c_str(), 0, 0); } if (port == UINT16_MAX) port = GetNextAvailablePort(); @@ -1909,6 +1937,9 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote // Spawn a new thread to accept the port that gets bound after // binding to port 0 (zero). + // ignore the hostname send from the remote end, just use the ip address + // that we're currently communicating with as the hostname + // Spawn a debugserver and try to get the port it listens to. ProcessLaunchInfo debugserver_launch_info; if (hostname.empty()) @@ -1916,9 +1947,19 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote if (log) log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port); + // Do not run in a new session so that it can not linger after the + // platform closes. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); - Error error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(), + std::string platform_scheme; + std::string platform_ip; + int platform_port; + std::string platform_path; + bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); + assert(ok); + Error error = StartDebugserverProcess ( + platform_ip.c_str(), port, debugserver_launch_info, port); @@ -2502,10 +2543,6 @@ GDBRemoteCommunicationServer::Handle_vCont (StringExtractorGDBRemote &packet) thread_actions.Append (thread_action); } - // If a default action for all other threads wasn't mentioned - // then we should stop the threads. - thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); - Error error = m_debugged_process_sp->Resume (thread_actions); if (error.Fail ()) { @@ -2983,7 +3020,7 @@ GDBRemoteCommunicationServer::Handle_qRegisterInfo (StringExtractorGDBRemote &pa return SendErrorResponse (69); // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) return SendErrorResponse (69); const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); @@ -3184,10 +3221,10 @@ GDBRemoteCommunicationServer::Handle_p (StringExtractorGDBRemote &packet) } // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) { if (log) - log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ()); + log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); return SendErrorResponse (0x15); } @@ -3264,7 +3301,8 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) } // Parse out the value. - const uint64_t raw_value = packet.GetHexMaxU64 (process_arch.GetByteOrder () == lldb::eByteOrderLittle, std::numeric_limits::max ()); + uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register + size_t reg_size = packet.GetHexBytesAvail (reg_bytes, sizeof(reg_bytes)); // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet); @@ -3284,7 +3322,7 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) return SendErrorResponse (0x15); } - const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex (reg_index); if (!reg_info) { if (log) @@ -3293,20 +3331,23 @@ GDBRemoteCommunicationServer::Handle_P (StringExtractorGDBRemote &packet) } // Return the end of registers response if we've iterated one past the end of the register set. - if (reg_index >= reg_context_sp->GetRegisterCount ()) + if (reg_index >= reg_context_sp->GetUserRegisterCount ()) { if (log) - log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetRegisterCount ()); + log->Printf ("GDBRemoteCommunicationServer::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ()); return SendErrorResponse (0x47); } + if (reg_size != reg_info->byte_size) + { + return SendIllFormedResponse (packet, "P packet register size is incorrect"); + } // Build the reginfos response. StreamGDBRemote response; - // FIXME Could be suffixed with a thread: parameter. - // That thread then needs to be fed back into the reg context retrieval above. - Error error = reg_context_sp->WriteRegisterFromUnsigned (reg_info, raw_value); + RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ()); + Error error = reg_context_sp->WriteRegister (reg_info, reg_value); if (error.Fail ()) { if (log) @@ -3393,6 +3434,46 @@ GDBRemoteCommunicationServer::Handle_H (StringExtractorGDBRemote &packet) return SendOKResponse(); } +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_I (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // Ensure we're llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_I() unimplemented"); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); + return SendErrorResponse (0x15); + } + + packet.SetFilePos (::strlen("I")); + char tmp[4096]; + for (;;) + { + size_t read = packet.GetHexBytesAvail(tmp, sizeof(tmp)); + if (read == 0) + { + break; + } + // write directly to stdin *this might block if stdin buffer is full* + // TODO: enqueue this block in circular buffer and send window size to remote host + ConnectionStatus status; + Error error; + m_stdio_communication.Write(tmp, read, status, &error); + if (error.Fail()) + { + return SendErrorResponse (0x15); + } + } + + return SendOKResponse(); +} + GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet) { @@ -3704,8 +3785,6 @@ GDBRemoteCommunicationServer::Handle_qMemoryRegionInfo (StringExtractorGDBRemote GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // We don't support if we're not llgs. if (!IsGdbServer()) return SendUnimplementedResponse (""); @@ -3713,12 +3792,13 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); return SendErrorResponse (0x15); } - // Parse out software or hardware breakpoint requested. + // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos (strlen("Z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier"); @@ -3726,61 +3806,82 @@ GDBRemoteCommunicationServer::Handle_Z (StringExtractorGDBRemote &packet) bool want_breakpoint = true; bool want_hardware = false; - const char breakpoint_type_char = packet.GetChar (); - switch (breakpoint_type_char) + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32 (eStoppointInvalid)); + switch (stoppoint_type) { - case '0': want_hardware = false; want_breakpoint = true; break; - case '1': want_hardware = true; want_breakpoint = true; break; - case '2': want_breakpoint = false; break; - case '3': want_breakpoint = false; break; - default: + case eBreakpointSoftware: + want_hardware = false; want_breakpoint = true; break; + case eBreakpointHardware: + want_hardware = true; want_breakpoint = true; break; + case eWatchpointWrite: + want_hardware = true; want_breakpoint = false; break; + case eWatchpointRead: + want_hardware = true; want_breakpoint = false; break; + case eWatchpointReadWrite: + want_hardware = true; want_breakpoint = false; break; + case eStoppointInvalid: return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after breakpoint type"); + return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after stoppoint type"); - // FIXME implement watchpoint support. - if (!want_breakpoint) - return SendUnimplementedResponse ("watchpoint support not yet implemented"); - - // Parse out the breakpoint address. + // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing address"); - const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address"); - // Parse out the breakpoint kind (i.e. size hint for opcode size). - const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits::max ()); - if (kind == std::numeric_limits::max ()) - return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse kind argument"); + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits::max ()); + if (size == std::numeric_limits::max ()) + return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse size argument"); if (want_breakpoint) { // Try to set the breakpoint. - const Error error = m_debugged_process_sp->SetBreakpoint (breakpoint_addr, kind, want_hardware); + const Error error = m_debugged_process_sp->SetBreakpoint (addr, size, want_hardware); if (error.Success ()) return SendOKResponse (); - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to set breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x09); - } + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to set breakpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); } + else + { + uint32_t watch_flags = + stoppoint_type == eWatchpointWrite + ? watch_flags = 0x1 // Write + : watch_flags = 0x3; // ReadWrite - // FIXME fix up after watchpoints are handled. - return SendUnimplementedResponse (""); + // Try to set the watchpoint. + const Error error = m_debugged_process_sp->SetWatchpoint ( + addr, size, watch_flags, want_hardware); + if (error.Success ()) + return SendOKResponse (); + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to set watchpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); + } } GDBRemoteCommunicationServer::PacketResult GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) { - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - // We don't support if we're not llgs. if (!IsGdbServer()) return SendUnimplementedResponse (""); @@ -3788,66 +3889,81 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) { + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); return SendErrorResponse (0x15); } - // Parse out software or hardware breakpoint requested. + // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos (strlen("z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier"); bool want_breakpoint = true; - const char breakpoint_type_char = packet.GetChar (); - switch (breakpoint_type_char) + const GDBStoppointType stoppoint_type = + GDBStoppointType(packet.GetS32 (eStoppointInvalid)); + switch (stoppoint_type) { - case '0': want_breakpoint = true; break; - case '1': want_breakpoint = true; break; - case '2': want_breakpoint = false; break; - case '3': want_breakpoint = false; break; + case eBreakpointHardware: want_breakpoint = true; break; + case eBreakpointSoftware: want_breakpoint = true; break; + case eWatchpointWrite: want_breakpoint = false; break; + case eWatchpointRead: want_breakpoint = false; break; + case eWatchpointReadWrite: want_breakpoint = false; break; default: return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') - return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after breakpoint type"); + return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after stoppoint type"); - // FIXME implement watchpoint support. - if (!want_breakpoint) - return SendUnimplementedResponse ("watchpoint support not yet implemented"); - - // Parse out the breakpoint address. + // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing address"); - const lldb::addr_t breakpoint_addr = packet.GetHexMaxU64(false, 0); + const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',') return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address"); - // Parse out the breakpoint kind (i.e. size hint for opcode size). - const uint32_t kind = packet.GetHexMaxU32 (false, std::numeric_limits::max ()); - if (kind == std::numeric_limits::max ()) - return SendIllFormedResponse(packet, "Malformed z packet, failed to parse kind argument"); + /* + // Parse out the stoppoint size (i.e. size hint for opcode size). + const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits::max ()); + if (size == std::numeric_limits::max ()) + return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument"); + */ if (want_breakpoint) { // Try to clear the breakpoint. - const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr); + const Error error = m_debugged_process_sp->RemoveBreakpoint (addr); if (error.Success ()) return SendOKResponse (); - else - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " failed to remove breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); - return SendErrorResponse (0x09); - } + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to remove breakpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); + } + else + { + // Try to clear the watchpoint. + const Error error = m_debugged_process_sp->RemoveWatchpoint (addr); + if (error.Success ()) + return SendOKResponse (); + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 + " failed to remove watchpoint: %s", + __FUNCTION__, + m_debugged_process_sp->GetID (), + error.AsCString ()); + return SendErrorResponse (0x09); } - - // FIXME fix up after watchpoints are handled. - return SendUnimplementedResponse (""); } GDBRemoteCommunicationServer::PacketResult @@ -4283,6 +4399,30 @@ GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote & return SendStopReplyPacketForThread (tid); } +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet) +{ + // Only the gdb server handles this. + if (!IsGdbServer ()) + return SendUnimplementedResponse (packet.GetStringRef ().c_str ()); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || + m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse (68); + + packet.SetFilePos(strlen("qWatchpointSupportInfo")); + if (packet.GetBytesLeft() == 0) + return SendOKResponse(); + if (packet.GetChar() != ':') + return SendErrorResponse(67); + + uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); + StreamGDBRemote response; + response.Printf ("num:%d;", num); + return SendPacketNoLock(response.GetData(), response.GetSize()); +} + void GDBRemoteCommunicationServer::FlushInferiorOutput () { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 07ce98e29ac6..dcf07844527e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -23,7 +23,7 @@ #include "lldb/Target/Process.h" #include "GDBRemoteCommunication.h" -#include "../../../Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeProcessProtocol.h" class ProcessGDBRemote; class StringExtractorGDBRemote; @@ -414,6 +414,9 @@ class GDBRemoteCommunicationServer : PacketResult Handle_H (StringExtractorGDBRemote &packet); + PacketResult + Handle_I (StringExtractorGDBRemote &packet); + PacketResult Handle_interrupt (StringExtractorGDBRemote &packet); @@ -465,6 +468,9 @@ class GDBRemoteCommunicationServer : PacketResult Handle_qThreadStopInfo (StringExtractorGDBRemote &packet); + PacketResult + Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet); + void SetCurrentThreadID (lldb::tid_t tid); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index fe99706969c8..cb0b4bb51007 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -42,6 +42,7 @@ #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" #include "lldb/Host/HostThread.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" @@ -431,11 +432,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } else if (name.compare("bitsize") == 0) { - reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT; + reg_info.byte_size = StringConvert::ToUInt32(value.c_str(), 0, 0) / CHAR_BIT; } else if (name.compare("offset") == 0) { - uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0); + uint32_t offset = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0); if (reg_offset != offset) { reg_offset = offset; @@ -483,11 +484,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } else if (name.compare("gcc") == 0) { - reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); + reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); } else if (name.compare("dwarf") == 0) { - reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); + reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); } else if (name.compare("generic") == 0) { @@ -502,7 +503,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { - uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); + uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); if (reg != LLDB_INVALID_REGNUM) value_regs.push_back (reg); } @@ -517,7 +518,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { - uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); + uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16); if (reg != LLDB_INVALID_REGNUM) invalidate_regs.push_back (reg); } @@ -941,6 +942,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) SetPrivateState (SetThreadStopInfo (m_last_stop_packet)); + m_stdio_disable = disable_stdio; if (!disable_stdio) { if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd) @@ -972,9 +974,12 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url) { Error error; // Only connect if we have a valid connect URL + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (connect_url && connect_url[0]) { + if (log) + log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url); std::unique_ptr conn_ap(new ConnectionFileDescriptor()); if (conn_ap.get()) { @@ -1656,17 +1661,17 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) if (name.compare("metype") == 0) { // exception type in big endian hex - exc_type = Args::StringToUInt32 (value.c_str(), 0, 16); + exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16); } else if (name.compare("medata") == 0) { // exception data in big endian hex - exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16)); + exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16)); } else if (name.compare("thread") == 0) { // thread in big endian hex - lldb::tid_t tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + lldb::tid_t tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); // m_thread_list_real does have its own mutex, but we need to // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) // and the m_thread_list_real.AddThread(...) so it doesn't change on us @@ -1702,12 +1707,12 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { value[comma_pos] = '\0'; // thread in big endian hex - tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); value.erase(0, comma_pos + 1); } - tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); + tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back (tid); } @@ -1726,7 +1731,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (name.compare("qaddr") == 0) { - thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16); + thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16); } else if (name.compare("reason") == 0) { @@ -1738,7 +1743,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // Swap "value" over into "name_extractor" desc_extractor.GetStringRef().swap(value); // Now convert the HEX bytes into a string value - desc_extractor.GetHexByteString (thread_name); + desc_extractor.GetHexByteString (value); + description.swap(value); } else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1])) { @@ -1747,7 +1753,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) // so it won't have to go and read it. if (gdb_thread) { - uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16); + uint32_t reg = StringConvert::ToUInt32 (name.c_str(), UINT32_MAX, 16); if (reg != UINT32_MAX) { @@ -1839,8 +1845,24 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (reason.compare("watchpoint") == 0) { - break_id_t watch_id = LLDB_INVALID_WATCH_ID; - // TODO: locate the watchpoint somehow... + StringExtractor desc_extractor(description.c_str()); + addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); + uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); + watch_id_t watch_id = LLDB_INVALID_WATCH_ID; + if (wp_addr != LLDB_INVALID_ADDRESS) + { + WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); + if (wp_sp) + { + wp_sp->SetHardwareIndex(wp_index); + watch_id = wp_sp->GetID(); + } + } + if (watch_id == LLDB_INVALID_WATCH_ID) + { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); + if (log) log->Printf ("failed to find watchpoint"); + } thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id)); handled = true; } @@ -2456,6 +2478,10 @@ ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error) ConnectionStatus status; m_stdio_communication.Write(src, src_len, status, NULL); } + else if (!m_stdio_disable) + { + m_gdb_comm.SendStdinNotification(src, src_len); + } return 0; } @@ -2760,6 +2786,10 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info static FileSpec g_debugserver_file_spec; ProcessLaunchInfo debugserver_launch_info; + // Make debugserver run in its own session so signals generated by + // special terminal key sequences (^C) don't affect debugserver. + debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); + debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false); debugserver_launch_info.SetUserID(process_info.GetUserID()); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 067449a289be..8935f7143e48 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" @@ -992,11 +993,11 @@ DWARFCompileUnit::ParseProducerInfo () { std::string str; if (regex_match.GetMatchAtIndex (producer_cstr, 1, str)) - m_producer_version_major = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); + m_producer_version_major = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); if (regex_match.GetMatchAtIndex (producer_cstr, 2, str)) - m_producer_version_minor = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); + m_producer_version_minor = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); if (regex_match.GetMatchAtIndex (producer_cstr, 3, str)) - m_producer_version_update = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); + m_producer_version_update = StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); } m_producer = eProducerClang; } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 10b51ffe0a8a..6a8c4e6d57b9 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -2294,22 +2294,26 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr (SymbolFileDWARF* dwarf2Data, if (dwarf2Data) { offset = GetOffset(); - - const DWARFAbbreviationDeclaration* abbrev_decl = cu->GetAbbreviations()->GetAbbreviationDeclaration (m_abbr_idx); - if (abbrev_decl) + + const DWARFAbbreviationDeclarationSet *abbrev_set = cu->GetAbbreviations(); + if (abbrev_set) { - // Make sure the abbreviation code still matches. If it doesn't and - // the DWARF data was mmap'ed, the backing file might have been modified - // which is bad news. - const uint64_t abbrev_code = dwarf2Data->get_debug_info_data().GetULEB128 (&offset); - - if (abbrev_decl->Code() == abbrev_code) - return abbrev_decl; + const DWARFAbbreviationDeclaration* abbrev_decl = abbrev_set->GetAbbreviationDeclaration (m_abbr_idx); + if (abbrev_decl) + { + // Make sure the abbreviation code still matches. If it doesn't and + // the DWARF data was mmap'ed, the backing file might have been modified + // which is bad news. + const uint64_t abbrev_code = dwarf2Data->get_debug_info_data().GetULEB128 (&offset); - dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("0x%8.8x: the DWARF debug information has been modified (abbrev code was %u, and is now %u)", - GetOffset(), - (uint32_t)abbrev_decl->Code(), - (uint32_t)abbrev_code); + if (abbrev_decl->Code() == abbrev_code) + return abbrev_decl; + + dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("0x%8.8x: the DWARF debug information has been modified (abbrev code was %u, and is now %u)", + GetOffset(), + (uint32_t)abbrev_decl->Code(), + (uint32_t)abbrev_code); + } } } offset = DW_INVALID_OFFSET; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b3a5476227f4..7ba4f52ac297 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -893,13 +893,22 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) // only 1 compile unit which is at offset zero in the DWARF. // TODO: modify to support LTO .o files where each .o file might // have multiple DW_TAG_compile_unit tags. - return info->GetCompileUnit(0).get(); + + DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0).get(); + if (dwarf_cu && dwarf_cu->GetUserData() == NULL) + dwarf_cu->SetUserData(comp_unit); + return dwarf_cu; } else { // Just a normal DWARF file whose user ID for the compile unit is // the DWARF offset itself - return info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get(); + + DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get(); + if (dwarf_cu && dwarf_cu->GetUserData() == NULL) + dwarf_cu->SetUserData(comp_unit); + return dwarf_cu; + } } return NULL; @@ -1037,23 +1046,6 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) return cu_sp; } -static void -AddRangesToBlock (Block& block, - DWARFDebugRanges::RangeList& ranges, - addr_t block_base_addr) -{ - const size_t num_ranges = ranges.GetSize(); - for (size_t i = 0; i= block_base_addr); - block.AddRange(Block::Range (range_base - block_base_addr, range.GetByteSize()));; - } - block.FinalizeRanges (); -} - - Function * SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die) { @@ -1397,8 +1389,24 @@ SymbolFileDWARF::ParseFunctionBlocks subprogram_low_pc = ranges.GetMinRangeBase(0); } } - - AddRangesToBlock (*block, ranges, subprogram_low_pc); + + const size_t num_ranges = ranges.GetSize(); + for (size_t i = 0; i= subprogram_low_pc) + block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize())); + else + { + GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": adding range [0x%" PRIx64 "-0x%" PRIx64 ") which has a base that is less than the function's low PC 0x%" PRIx64 ". Please file a bug and attach the file at the start of this error message", + block->GetID(), + range_base, + range.GetRangeEnd(), + subprogram_low_pc); + } + } + block->FinalizeRanges (); if (tag != DW_TAG_subprogram && (name != NULL || mangled_name != NULL)) { @@ -2786,6 +2794,59 @@ SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn return false; } + + +SymbolFileDWARF::GlobalVariableMap & +SymbolFileDWARF::GetGlobalAranges() +{ + if (!m_global_aranges_ap) + { + m_global_aranges_ap.reset (new GlobalVariableMap()); + + ModuleSP module_sp = GetObjectFile()->GetModule(); + if (module_sp) + { + const size_t num_cus = module_sp->GetNumCompileUnits(); + for (size_t i = 0; i < num_cus; ++i) + { + CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(i); + if (cu_sp) + { + VariableListSP globals_sp = cu_sp->GetVariableList(true); + if (globals_sp) + { + const size_t num_globals = globals_sp->GetSize(); + for (size_t g = 0; g < num_globals; ++g) + { + VariableSP var_sp = globals_sp->GetVariableAtIndex(g); + if (var_sp && !var_sp->GetLocationIsConstantValueData()) + { + const DWARFExpression &location = var_sp->LocationExpression(); + Value location_result; + Error error; + if (location.Evaluate(NULL, NULL, NULL, LLDB_INVALID_ADDRESS, NULL, location_result, &error)) + { + if (location_result.GetValueType() == Value::eValueTypeFileAddress) + { + lldb::addr_t file_addr = location_result.GetScalar().ULongLong(); + lldb::addr_t byte_size = 1; + if (var_sp->GetType()) + byte_size = var_sp->GetType()->GetByteSize(); + m_global_aranges_ap->Append(GlobalVariableMap::Entry(file_addr, byte_size, var_sp.get())); + } + } + } + } + } + } + } + } + m_global_aranges_ap->Sort(); + } + return *m_global_aranges_ap; +} + + uint32_t SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) { @@ -2794,10 +2855,11 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ static_cast(so_addr.GetSection().get()), so_addr.GetOffset(), resolve_scope); uint32_t resolved = 0; - if (resolve_scope & ( eSymbolContextCompUnit | - eSymbolContextFunction | - eSymbolContextBlock | - eSymbolContextLineEntry)) + if (resolve_scope & ( eSymbolContextCompUnit | + eSymbolContextFunction | + eSymbolContextBlock | + eSymbolContextLineEntry | + eSymbolContextVariable )) { lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); @@ -2805,7 +2867,30 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_ if (debug_info) { const dw_offset_t cu_offset = debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr); - if (cu_offset != DW_INVALID_OFFSET) + if (cu_offset == DW_INVALID_OFFSET) + { + // Global variables are not in the compile unit address ranges. The only way to + // currently find global variables is to iterate over the .debug_pubnames or the + // __apple_names table and find all items in there that point to DW_TAG_variable + // DIEs and then find the address that matches. + if (resolve_scope & eSymbolContextVariable) + { + GlobalVariableMap &map = GetGlobalAranges(); + const GlobalVariableMap::Entry *entry = map.FindEntryThatContains(file_vm_addr); + if (entry && entry->data) + { + Variable *variable = entry->data; + SymbolContextScope *scc = variable->GetSymbolContextScope(); + if (scc) + { + scc->CalculateSymbolContext(&sc); + sc.variable = variable; + } + return sc.GetResolvedMask(); + } + } + } + else { uint32_t cu_idx = DW_INVALID_INDEX; DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get(); @@ -3409,9 +3494,11 @@ SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu, // Parse all blocks if needed if (inlined_die) { - sc.block = sc.function->GetBlock (true).FindBlockByID (MakeUserID(inlined_die->GetOffset())); - assert (sc.block != NULL); - if (sc.block->GetStartAddress (addr) == false) + Block &function_block = sc.function->GetBlock (true); + sc.block = function_block.FindBlockByID (MakeUserID(inlined_die->GetOffset())); + if (sc.block == NULL) + sc.block = function_block.FindBlockByID (inlined_die->GetOffset()); + if (sc.block == NULL || sc.block->GetStartAddress (addr) == false) addr.Clear(); } else @@ -6906,7 +6993,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type); - byte_size = clang_type.GetByteSize(); + byte_size = clang_type.GetByteSize(nullptr); type_sp.reset( new Type (MakeUserID(die->GetOffset()), this, diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 230e1a5d3984..d8efdbcb38a4 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -29,6 +29,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/Flags.h" +#include "lldb/Core/RangeMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolFile.h" @@ -557,6 +558,11 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::Us uint32_t type_mask, TypeSet &type_set); + typedef lldb_private::RangeDataVector GlobalVariableMap; + + GlobalVariableMap & + GetGlobalAranges(); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap * m_debug_map_symfile; clang::TranslationUnitDecl * m_clang_tu_decl; @@ -584,6 +590,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::Us std::unique_ptr m_apple_types_ap; std::unique_ptr m_apple_namespaces_ap; std::unique_ptr m_apple_objc_ap; + std::unique_ptr m_global_aranges_ap; NameToDIE m_function_basename_index; // All concrete functions NameToDIE m_function_fullname_index; // All concrete functions NameToDIE m_function_method_index; // All inlined functions diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 7e484bd8dc73..0eb0f83d5f35 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Error.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/Log.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamString.h" @@ -146,8 +147,9 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& if (log && log->GetVerbose ()) { StreamString strm; - const char *disassemble_format = "${frame.pc}: "; - inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, disassemble_format); + lldb_private::FormatEntity::Entry format; + FormatEntity::Parse("${frame.pc}: ", format); + inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL, NULL, NULL, &format); log->PutCString (strm.GetData()); } diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index d851ae792181..da25eb84f19e 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -11,7 +11,7 @@ // C Includes // C++ Includes -#include +#include // std::once #include // Other libraries and framework includes @@ -708,7 +708,7 @@ uint32_t ClangASTContext::GetPointerByteSize () { if (m_pointer_byte_size == 0) - m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid).GetPointerType().GetByteSize(); + m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid).GetPointerType().GetByteSize(nullptr); return m_pointer_byte_size; } diff --git a/source/Symbol/ClangASTType.cpp b/source/Symbol/ClangASTType.cpp index 8b672fac4312..eaff90ab8a0a 100644 --- a/source/Symbol/ClangASTType.cpp +++ b/source/Symbol/ClangASTType.cpp @@ -289,6 +289,37 @@ ClangASTType::IsArrayType (ClangASTType *element_type_ptr, return 0; } +bool +ClangASTType::IsVectorType (ClangASTType *element_type, + uint64_t *size) const +{ + if (IsValid()) + { + clang::QualType qual_type (GetCanonicalQualType()); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::Vector: + { + const clang::VectorType *vector_type = qual_type->getAs(); + if (vector_type) + { + if (size) + *size = vector_type->getNumElements(); + if (element_type) + *element_type = ClangASTType(m_ast, vector_type->getElementType().getAsOpaquePtr()); + } + return true; + } + break; + default: + break; + } + } + return false; +} + bool ClangASTType::IsRuntimeGeneratedType () const { @@ -1663,7 +1694,7 @@ ClangASTType::GetArrayElementType (uint64_t *stride) const // TODO: the real stride will be >= this value.. find the real one! if (stride) - *stride = element_type.GetByteSize(); + *stride = element_type.GetByteSize(nullptr); return element_type; @@ -2062,28 +2093,59 @@ ClangASTType::GetBasicTypeFromAST (lldb::BasicType basic_type) const //---------------------------------------------------------------------- uint64_t -ClangASTType::GetBitSize () const +ClangASTType::GetBitSize (ExecutionContext *exe_ctx) const { if (GetCompleteType ()) { clang::QualType qual_type(GetCanonicalQualType()); - const uint32_t bit_size = m_ast->getTypeSize (qual_type); - if (bit_size == 0) + switch (qual_type->getTypeClass()) { - if (qual_type->isIncompleteArrayType()) - return m_ast->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified()); + case clang::Type::ObjCInterface: + case clang::Type::ObjCObject: + if (exe_ctx && exe_ctx->GetProcessPtr()) + { + ObjCLanguageRuntime *objc_runtime = exe_ctx->GetProcessPtr()->GetObjCLanguageRuntime(); + if (objc_runtime) + { + uint64_t bit_size = 0; + if (objc_runtime->GetTypeBitSize(*this, bit_size)) + return bit_size; + } + } + else + { + static bool g_printed = false; + if (!g_printed) + { + StreamString s; + s.Printf("warning: trying to determine the size of type "); + DumpTypeDescription(&s); + s.Printf("\n without a valid ExecutionContext. this is not reliable. please file a bug against LLDB.\nbacktrace:\n"); + Host::Backtrace(s, 10); + printf("%s\n", s.GetData()); + g_printed = true; + } + } + // fallthrough + default: + const uint32_t bit_size = m_ast->getTypeSize (qual_type); + if (bit_size == 0) + { + if (qual_type->isIncompleteArrayType()) + return m_ast->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified()); + } + if (qual_type->isObjCObjectOrInterfaceType()) + return bit_size + m_ast->getTypeSize(m_ast->ObjCBuiltinClassTy); + return bit_size; } - if (qual_type->isObjCObjectOrInterfaceType()) - return bit_size + m_ast->getTypeSize(m_ast->ObjCBuiltinClassTy); - return bit_size; } return 0; } uint64_t -ClangASTType::GetByteSize () const +ClangASTType::GetByteSize (ExecutionContext *exe_ctx) const { - return (GetBitSize () + 7) / 8; + return (GetBitSize (exe_ctx) + 7) / 8; } size_t @@ -3416,7 +3478,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, child_byte_offset = bit_offset/8; ClangASTType base_class_clang_type(m_ast, base_class->getType()); child_name = base_class_clang_type.GetTypeName().AsCString(""); - uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(); + uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(nullptr); // Base classes bit sizes should be a multiple of 8 bits in size assert (base_class_clang_type_bit_size % 8 == 0); @@ -3444,7 +3506,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, // alignment (field_type_info.second) from the AST context. ClangASTType field_clang_type (m_ast, field->getType()); assert(field_idx < record_layout.getFieldCount()); - child_byte_size = field_clang_type.GetByteSize(); + child_byte_size = field_clang_type.GetByteSize(exe_ctx); // Figure out the field offset within the current struct/union/class type bit_offset = record_layout.getFieldOffset (field_idx); @@ -3609,7 +3671,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, // We have a pointer to an simple type if (idx == 0 && pointee_clang_type.GetCompleteType()) { - child_byte_size = pointee_clang_type.GetByteSize(); + child_byte_size = pointee_clang_type.GetByteSize(exe_ctx); child_byte_offset = 0; return pointee_clang_type; } @@ -3630,7 +3692,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, char element_name[64]; ::snprintf (element_name, sizeof (element_name), "[%zu]", idx); child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(); + child_byte_size = element_type.GetByteSize(exe_ctx); child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; return element_type; } @@ -3651,7 +3713,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, char element_name[64]; ::snprintf (element_name, sizeof (element_name), "[%zu]", idx); child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(); + child_byte_size = element_type.GetByteSize(exe_ctx); child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; return element_type; } @@ -3701,7 +3763,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, // We have a pointer to an simple type if (idx == 0) { - child_byte_size = pointee_clang_type.GetByteSize(); + child_byte_size = pointee_clang_type.GetByteSize(exe_ctx); child_byte_offset = 0; return pointee_clang_type; } @@ -3745,7 +3807,7 @@ ClangASTType::GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, // We have a pointer to an simple type if (idx == 0) { - child_byte_size = pointee_clang_type.GetByteSize(); + child_byte_size = pointee_clang_type.GetByteSize(exe_ctx); child_byte_offset = 0; return pointee_clang_type; } @@ -6643,7 +6705,7 @@ ClangASTType::GetValueAsScalar (const lldb_private::DataExtractor &data, if (encoding == lldb::eEncodingInvalid || count != 1) return false; - const uint64_t byte_size = GetByteSize(); + const uint64_t byte_size = GetByteSize(nullptr); lldb::offset_t offset = data_byte_offset; switch (encoding) { @@ -6771,7 +6833,7 @@ ClangASTType::SetValueFromScalar (const Scalar &value, Stream &strm) if (encoding == lldb::eEncodingInvalid || count != 1) return false; - const uint64_t bit_width = GetBitSize(); + const uint64_t bit_width = GetBitSize(nullptr); // This function doesn't currently handle non-byte aligned assignments if ((bit_width % 8) != 0) return false; @@ -6851,7 +6913,7 @@ ClangASTType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx, if (!GetCompleteType()) return false; - const uint64_t byte_size = GetByteSize(); + const uint64_t byte_size = GetByteSize(exe_ctx); if (data.GetByteSize() < byte_size) { lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0')); @@ -6901,7 +6963,7 @@ ClangASTType::WriteToMemory (lldb_private::ExecutionContext *exe_ctx, if (!GetCompleteType()) return false; - const uint64_t byte_size = GetByteSize(); + const uint64_t byte_size = GetByteSize(exe_ctx); if (byte_size > 0) { diff --git a/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp index 8c6a2e7214c3..e7153446cd16 100644 --- a/source/Symbol/CompactUnwindInfo.cpp +++ b/source/Symbol/CompactUnwindInfo.cpp @@ -809,8 +809,16 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi } } + if (mode == UNWIND_X86_64_MODE_STACK_IND) + { + row->SetCFAOffset (stack_size); + } + else + { + row->SetCFAOffset (stack_size * wordsize); + } + row->SetCFARegister (x86_64_eh_regnum::rsp); - row->SetCFAOffset (stack_size * wordsize); row->SetOffset (0); row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); @@ -919,10 +927,10 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi case UNWIND_X86_64_REG_R14: case UNWIND_X86_64_REG_R15: case UNWIND_X86_64_REG_RBP: - row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true); + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true); + saved_registers_offset++; break; } - saved_registers_offset++; } } unwind_plan.AppendRow (row); @@ -1084,7 +1092,16 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function } row->SetCFARegister (i386_eh_regnum::esp); - row->SetCFAOffset (stack_size * wordsize); + + if (mode == UNWIND_X86_MODE_STACK_IND) + { + row->SetCFAOffset (stack_size); + } + else + { + row->SetCFAOffset (stack_size * wordsize); + } + row->SetOffset (0); row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); @@ -1193,10 +1210,10 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function case UNWIND_X86_REG_EDI: case UNWIND_X86_REG_ESI: case UNWIND_X86_REG_EBP: - row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true); + row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true); + saved_registers_offset++; break; } - saved_registers_offset++; } } diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp index 129f4def0067..62ae6ac464ce 100644 --- a/source/Symbol/SymbolContext.cpp +++ b/source/Symbol/SymbolContext.cpp @@ -13,7 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Host.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" @@ -21,6 +21,7 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Variable.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -33,7 +34,8 @@ SymbolContext::SymbolContext() : function (nullptr), block (nullptr), line_entry (), - symbol (nullptr) + symbol (nullptr), + variable (nullptr) { } @@ -44,7 +46,8 @@ SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Bl function (f), block (b), line_entry (), - symbol (s) + symbol (s), + variable (nullptr) { if (le) line_entry = *le; @@ -57,7 +60,8 @@ SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit * function (f), block (b), line_entry (), - symbol (s) + symbol (s), + variable (nullptr) { if (le) line_entry = *le; @@ -70,7 +74,8 @@ SymbolContext::SymbolContext(const SymbolContext& rhs) : function (rhs.function), block (rhs.block), line_entry (rhs.line_entry), - symbol (rhs.symbol) + symbol (rhs.symbol), + variable (rhs.variable) { } @@ -82,7 +87,8 @@ SymbolContext::SymbolContext (SymbolContextScope *sc_scope) : function (nullptr), block (nullptr), line_entry (), - symbol (nullptr) + symbol (nullptr), + variable (nullptr) { sc_scope->CalculateSymbolContext (this); } @@ -103,6 +109,7 @@ SymbolContext::operator= (const SymbolContext& rhs) block = rhs.block; line_entry = rhs.line_entry; symbol = rhs.symbol; + variable = rhs.variable; } return *this; } @@ -118,6 +125,7 @@ SymbolContext::Clear(bool clear_target) block = nullptr; line_entry.Clear(); symbol = nullptr; + variable = nullptr; } bool @@ -309,6 +317,37 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *t symbol->GetDescription(s, level, target); s->EOL(); } + + if (variable != nullptr) + { + s->Indent(" Variable: "); + + s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID()); + + switch (variable->GetScope()) + { + case eValueTypeVariableGlobal: + s->PutCString("kind = global, "); + break; + + case eValueTypeVariableStatic: + s->PutCString("kind = static, "); + break; + + case eValueTypeVariableArgument: + s->PutCString("kind = argument, "); + break; + + case eValueTypeVariableLocal: + s->PutCString("kind = local, "); + break; + + default: + break; + } + + s->Printf ("name = \"%s\"\n", variable->GetName().GetCString()); + } } uint32_t @@ -322,6 +361,7 @@ SymbolContext::GetResolvedMask () const if (block) resolved_mask |= eSymbolContextBlock; if (line_entry.IsValid()) resolved_mask |= eSymbolContextLineEntry; if (symbol) resolved_mask |= eSymbolContextSymbol; + if (variable) resolved_mask |= eSymbolContextVariable; return resolved_mask; } @@ -377,6 +417,12 @@ SymbolContext::Dump(Stream *s, Target *target) const if (symbol != nullptr && symbol->GetMangled()) *s << ' ' << symbol->GetMangled().GetName().AsCString(); s->EOL(); + *s << "Variable = " << (void *)variable; + if (variable != nullptr) + { + *s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName(); + s->EOL(); + } s->IndentLess(); s->IndentLess(); } @@ -389,7 +435,8 @@ lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs) && lhs.module_sp.get() == rhs.module_sp.get() && lhs.comp_unit == rhs.comp_unit && lhs.target_sp.get() == rhs.target_sp.get() - && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0; + && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 + && lhs.variable == rhs.variable; } bool @@ -400,7 +447,8 @@ lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs) || lhs.module_sp.get() != rhs.module_sp.get() || lhs.comp_unit != rhs.comp_unit || lhs.target_sp.get() != rhs.target_sp.get() - || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0; + || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 + || lhs.variable != rhs.variable; } bool @@ -730,12 +778,12 @@ SymbolContextSpecifier::AddSpecification (const char *spec_string, Specification m_type |= eFileSpecified; break; case eLineStartSpecified: - m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value); + m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); if (return_value) m_type |= eLineStartSpecified; break; case eLineEndSpecified: - m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value); + m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); if (return_value) m_type |= eLineEndSpecified; break; diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp index 42b76590aaea..6e67f4695d9f 100644 --- a/source/Symbol/Type.cpp +++ b/source/Symbol/Type.cpp @@ -336,7 +336,7 @@ Type::GetByteSize() if (encoding_type) m_byte_size = encoding_type->GetByteSize(); if (m_byte_size == 0) - m_byte_size = GetClangLayoutType().GetByteSize(); + m_byte_size = GetClangLayoutType().GetByteSize(nullptr); } break; @@ -1141,7 +1141,7 @@ TypeImpl::GetPointerType () const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetPointerType()); + return TypeImpl(m_static_type.GetPointerType(), m_dynamic_type.GetPointerType()); } return TypeImpl(m_static_type.GetPointerType()); } @@ -1156,7 +1156,7 @@ TypeImpl::GetPointeeType () const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetPointeeType()); + return TypeImpl(m_static_type.GetPointeeType(), m_dynamic_type.GetPointeeType()); } return TypeImpl(m_static_type.GetPointeeType()); } @@ -1171,7 +1171,7 @@ TypeImpl::GetReferenceType () const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetLValueReferenceType()); + return TypeImpl(m_static_type.GetReferenceType(), m_dynamic_type.GetLValueReferenceType()); } return TypeImpl(m_static_type.GetReferenceType()); } @@ -1186,7 +1186,7 @@ TypeImpl::GetTypedefedType () const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetTypedefedType()); + return TypeImpl(m_static_type.GetTypedefedType(), m_dynamic_type.GetTypedefedType()); } return TypeImpl(m_static_type.GetTypedefedType()); } @@ -1201,7 +1201,7 @@ TypeImpl::GetDereferencedType () const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetNonReferenceType()); + return TypeImpl(m_static_type.GetDereferencedType(), m_dynamic_type.GetNonReferenceType()); } return TypeImpl(m_static_type.GetDereferencedType()); } @@ -1216,7 +1216,7 @@ TypeImpl::GetUnqualifiedType() const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetFullyUnqualifiedType()); + return TypeImpl(m_static_type.GetUnqualifiedType(), m_dynamic_type.GetFullyUnqualifiedType()); } return TypeImpl(m_static_type.GetUnqualifiedType()); } @@ -1231,7 +1231,7 @@ TypeImpl::GetCanonicalType() const { if (m_dynamic_type.IsValid()) { - return TypeImpl(m_static_type, m_dynamic_type.GetCanonicalType()); + return TypeImpl(m_static_type.GetCanonicalType(), m_dynamic_type.GetCanonicalType()); } return TypeImpl(m_static_type.GetCanonicalType()); } diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp index b1a60f6b4a24..4c03a307296d 100644 --- a/source/Symbol/Variable.cpp +++ b/source/Symbol/Variable.cpp @@ -203,7 +203,10 @@ void Variable::CalculateSymbolContext (SymbolContext *sc) { if (m_owner_scope) + { m_owner_scope->CalculateSymbolContext(sc); + sc->variable = this; + } else sc->Clear(false); } diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp index db4025f40c05..e03a560bd063 100644 --- a/source/Target/ExecutionContext.cpp +++ b/source/Target/ExecutionContext.cpp @@ -705,7 +705,11 @@ ExecutionContextRef::SetTargetPtr (Target* target, bool adopt_selected) if (process_sp) { // Only fill in the thread and frame if our process is stopped - if (StateIsStoppedState (process_sp->GetState(), true)) + // Don't just check the state, since we might be in the middle of + // resuming. + Process::StopLocker stop_locker; + + if (stop_locker.TryLock(&process_sp->GetRunLock()) && StateIsStoppedState (process_sp->GetState(), true)) { lldb::ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); if (!thread_sp) diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp index 358bffee3a4d..123ee93d322f 100644 --- a/source/Target/LanguageRuntime.cpp +++ b/source/Target/LanguageRuntime.cpp @@ -337,6 +337,9 @@ struct language_name_pair language_names[] = { "swift", eLanguageTypeSwift }, { "julia", eLanguageTypeJulia }, { "dylan", eLanguageTypeDylan }, + { "c++14", eLanguageTypeC_plus_plus_14 }, + { "fortran03", eLanguageTypeFortran03 }, + { "fortran08", eLanguageTypeFortran08 }, // Now synonyms, in arbitrary order { "objc", eLanguageTypeObjC }, { "objc++", eLanguageTypeObjC_plus_plus } diff --git a/source/Target/ObjCLanguageRuntime.cpp b/source/Target/ObjCLanguageRuntime.cpp index b182407bf68e..3d7a9021343a 100644 --- a/source/Target/ObjCLanguageRuntime.cpp +++ b/source/Target/ObjCLanguageRuntime.cpp @@ -34,9 +34,14 @@ ObjCLanguageRuntime::~ObjCLanguageRuntime() ObjCLanguageRuntime::ObjCLanguageRuntime (Process *process) : LanguageRuntime (process), + m_impl_cache(), m_has_new_literals_and_indexing (eLazyBoolCalculate), m_isa_to_descriptor(), - m_isa_to_descriptor_stop_id (UINT32_MAX) + m_hash_to_isa_map(), + m_type_size_cache(), + m_isa_to_descriptor_stop_id (UINT32_MAX), + m_complete_class_cache(), + m_negative_complete_class_cache() { } @@ -626,3 +631,42 @@ ObjCLanguageRuntime::GetEncodingToType () { return nullptr; } + +bool +ObjCLanguageRuntime::GetTypeBitSize (const ClangASTType& clang_type, + uint64_t &size) +{ + void *opaque_ptr = clang_type.GetQualType().getAsOpaquePtr(); + size = m_type_size_cache.Lookup(opaque_ptr); + // an ObjC object will at least have an ISA, so 0 is definitely not OK + if (size > 0) + return true; + + ClassDescriptorSP class_descriptor_sp = GetClassDescriptorFromClassName(clang_type.GetTypeName()); + if (!class_descriptor_sp) + return false; + + int32_t max_offset = INT32_MIN; + uint64_t sizeof_max = 0; + bool found = false; + + for (size_t idx = 0; + idx < class_descriptor_sp->GetNumIVars(); + idx++) + { + const auto& ivar = class_descriptor_sp->GetIVarAtIndex(idx); + int32_t cur_offset = ivar.m_offset; + if (cur_offset > max_offset) + { + max_offset = cur_offset; + sizeof_max = ivar.m_size; + found = true; + } + } + + size = 8 * (max_offset + sizeof_max); + if (found) + m_type_size_cache.Insert(opaque_ptr, size); + + return found; +} diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp index 4ebd18b8bfd0..09c9efc14b08 100644 --- a/source/Target/Platform.cpp +++ b/source/Target/Platform.cpp @@ -286,8 +286,7 @@ Platform::Platform (bool is_host) : m_minor_os_version (UINT32_MAX), m_update_os_version (UINT32_MAX), m_system_arch(), - m_uid_map_mutex (Mutex::eMutexTypeNormal), - m_gid_map_mutex (Mutex::eMutexTypeNormal), + m_mutex (Mutex::eMutexTypeRecursive), m_uid_map(), m_gid_map(), m_max_uid_name_len (0), @@ -299,8 +298,7 @@ Platform::Platform (bool is_host) : m_ssh_opts (), m_ignores_remote_hostname (false), m_trap_handlers(), - m_calculated_trap_handlers (false), - m_trap_handler_mutex() + m_calculated_trap_handlers (false) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); if (log) @@ -384,6 +382,8 @@ Platform::GetOSVersion (uint32_t &major, uint32_t &minor, uint32_t &update) { + Mutex::Locker locker (m_mutex); + bool success = m_major_os_version != UINT32_MAX; if (IsHost()) { @@ -463,7 +463,7 @@ Platform::GetOSKernelDescription (std::string &s) } void -Platform::AddClangModuleCompilationOptions (std::vector &options) +Platform::AddClangModuleCompilationOptions (Target *target, std::vector &options) { std::vector default_compilation_options = { @@ -1103,6 +1103,20 @@ Platform::LaunchProcess (ProcessLaunchInfo &launch_info) return error; } +Error +Platform::KillProcess (const lldb::pid_t pid) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf ("Platform::%s, pid %" PRIu64, __FUNCTION__, pid); + + if (!IsHost ()) + return Error ("base lldb_private::Platform class can't launch remote processes"); + + Host::Kill (pid, SIGTERM); + return Error(); +} + lldb::ProcessSP Platform::DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, @@ -1233,7 +1247,64 @@ Platform::PutFile (const FileSpec& source, uint32_t uid, uint32_t gid) { - Error error("unimplemented"); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("[PutFile] Using block by block transfer....\n"); + + uint32_t source_open_options = File::eOpenOptionRead; + if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) + source_open_options |= File::eOpenoptionDontFollowSymlinks; + + File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); + Error error; + uint32_t permissions = source_file.GetPermissions(error); + if (permissions == 0) + permissions = lldb::eFilePermissionsFileDefault; + + if (!source_file.IsValid()) + return Error("PutFile: unable to open source file"); + lldb::user_id_t dest_file = OpenFile (destination, + File::eOpenOptionCanCreate | + File::eOpenOptionWrite | + File::eOpenOptionTruncate, + permissions, + error); + if (log) + log->Printf ("dest_file = %" PRIu64 "\n", dest_file); + + if (error.Fail()) + return error; + if (dest_file == UINT64_MAX) + return Error("unable to open target file"); + lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); + uint64_t offset = 0; + for (;;) + { + size_t bytes_read = buffer_sp->GetByteSize(); + error = source_file.Read(buffer_sp->GetBytes(), bytes_read); + if (error.Fail() || bytes_read == 0) + break; + + const uint64_t bytes_written = WriteFile(dest_file, offset, + buffer_sp->GetBytes(), bytes_read, error); + if (error.Fail()) + break; + + offset += bytes_written; + if (bytes_written != bytes_read) + { + // We didn't write the correct number of bytes, so adjust + // the file position in the source file we are reading from... + source_file.SeekFromStart(offset); + } + } + CloseFile(dest_file, error); + + if (uid == UINT32_MAX && gid == UINT32_MAX) + return error; + + // TODO: ChownFile? + return error; } @@ -1528,7 +1599,7 @@ Platform::GetTrapHandlerSymbolNames () { if (!m_calculated_trap_handlers) { - Mutex::Locker locker (m_trap_handler_mutex); + Mutex::Locker locker (m_mutex); if (!m_calculated_trap_handlers) { CalculateTrapHandlerSymbolNames(); diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp index 106678da2684..f7a26f676aba 100644 --- a/source/Target/Process.cpp +++ b/source/Target/Process.cpp @@ -720,6 +720,7 @@ Process::Process(Target &target, Listener &listener, const UnixSignalsSP &unix_s m_process_input_reader (), m_stdio_communication ("process.stdio"), m_stdio_communication_mutex (Mutex::eMutexTypeRecursive), + m_stdio_disable(true), m_stdout_data (), m_stderr_data (), m_profile_data_comm_mutex (Mutex::eMutexTypeRecursive), @@ -3121,6 +3122,11 @@ Process::Launch (ProcessLaunchInfo &launch_info) StartPrivateStateThread (); m_stop_info_override_callback = GetTarget().GetArchitecture().GetStopInfoOverrideCallback(); + + // Target was stopped at entry as was intended. Need to notify the listeners + // about it. + if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == true) + HandlePrivateEvent(event_sp); } else if (state == eStateExited) { @@ -3643,7 +3649,8 @@ Process::PrivateResume () } else { - // Somebody wanted to run without running. So generate a continue & a stopped event, + // Somebody wanted to run without running (e.g. we were faking a step from one frame of a set of inlined + // frames that share the same PC to another.) So generate a continue & a stopped event, // and let the world handle them. if (log) log->Printf ("Process::PrivateResume() asked to simulate a start & stop."); @@ -3905,6 +3912,7 @@ Process::Destroy () } m_stdio_communication.StopReadThread(); m_stdio_communication.Disconnect(); + m_stdio_disable = true; if (m_process_input_reader) { diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp index 451c42d18bfa..b841b2c066a3 100644 --- a/source/Target/ProcessLaunchInfo.cpp +++ b/source/Target/ProcessLaunchInfo.cpp @@ -344,7 +344,14 @@ ProcessLaunchInfo::FinalizeFileActions (Target *target, bool default_to_use_pty) log->Printf ("ProcessLaunchInfo::%s default_to_use_pty is set, and at least one stdin/stderr/stdout is unset, so generating a pty to use for it", __FUNCTION__); - if (m_pty->OpenFirstAvailableMaster(O_RDWR| O_NOCTTY, NULL, 0)) + int open_flags = O_RDWR | O_NOCTTY; +#if !defined(_MSC_VER) + // We really shouldn't be specifying platform specific flags + // that are intended for a system call in generic code. But + // this will have to do for now. + open_flags |= O_CLOEXEC; +#endif + if (m_pty->OpenFirstAvailableMaster(open_flags, NULL, 0)) { const char *slave_path = m_pty->GetSlaveName(NULL, 0); diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp index c46db4cfadf9..01a8c9ab88f2 100644 --- a/source/Target/StackFrame.cpp +++ b/source/Target/StackFrame.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -1373,11 +1374,11 @@ StackFrame::DumpUsingSettingsFormat (Stream *strm, const char *frame_marker) if (frame_marker) s.PutCString(frame_marker); - const char *frame_format = NULL; + const FormatEntity::Entry *frame_format = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) frame_format = target->GetDebugger().GetFrameFormat(); - if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s)) + if (frame_format && FormatEntity::Format(*frame_format, s, &m_sc, &exe_ctx, NULL, NULL, false, false)) { strm->Write(s.GetData(), s.GetSize()); } diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp index 4b57ca65a2df..457b94c1dc20 100644 --- a/source/Target/StopInfo.cpp +++ b/source/Target/StopInfo.cpp @@ -479,7 +479,12 @@ class StopInfoBreakpoint : public StopInfo condition_says_stop); } if (!condition_says_stop) + { + // We don't want to increment the hit count of breakpoints if the condition fails. + // We've already bumped it by the time we get here, so undo the bump: + bp_loc_sp->UndoBumpHitCount(); continue; + } } } diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp index 28ad47e3d81d..bbed0fb0bc12 100644 --- a/source/Target/TargetList.cpp +++ b/source/Target/TargetList.cpp @@ -98,12 +98,12 @@ TargetList::CreateTarget (Debugger &debugger, Error TargetList::CreateTargetInternal (Debugger &debugger, - const char *user_exe_path, - const char *triple_cstr, - bool get_dependent_files, - const OptionGroupPlatform *platform_options, - TargetSP &target_sp, - bool is_dummy_target) + const char *user_exe_path, + const char *triple_cstr, + bool get_dependent_files, + const OptionGroupPlatform *platform_options, + TargetSP &target_sp, + bool is_dummy_target) { Error error; PlatformSP platform_sp; @@ -126,16 +126,24 @@ TargetList::CreateTargetInternal (Debugger &debugger, bool prefer_platform_arch = false; CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); + + // let's see if there is already an existing plaform before we go creating another... + platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); + if (platform_options && platform_options->PlatformWasSpecified ()) { - const bool select_platform = true; - platform_sp = platform_options->CreatePlatformWithOptions (interpreter, - arch, - select_platform, - error, - platform_arch); - if (!platform_sp) - return error; + // Create a new platform if it doesn't match the selected platform + if (!platform_options->PlatformMatches(platform_sp)) + { + const bool select_platform = true; + platform_sp = platform_options->CreatePlatformWithOptions (interpreter, + arch, + select_platform, + error, + platform_arch); + if (!platform_sp) + return error; + } } if (user_exe_path && user_exe_path[0]) @@ -361,12 +369,12 @@ TargetList::CreateDummyTarget (Debugger &debugger, Error TargetList::CreateTargetInternal (Debugger &debugger, - const char *user_exe_path, - const ArchSpec& specified_arch, - bool get_dependent_files, - lldb::PlatformSP &platform_sp, - lldb::TargetSP &target_sp, - bool is_dummy_target) + const char *user_exe_path, + const ArchSpec& specified_arch, + bool get_dependent_files, + lldb::PlatformSP &platform_sp, + lldb::TargetSP &target_sp, + bool is_dummy_target) { Timer scoped_timer (__PRETTY_FUNCTION__, diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp index b532d8d71c8f..6fd5cdf0d15c 100644 --- a/source/Target/Thread.cpp +++ b/source/Target/Thread.cpp @@ -13,6 +13,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" +#include "lldb/Core/FormatEntity.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" @@ -66,8 +67,8 @@ g_properties[] = { "step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, step-in will not stop in functions with no debug information." }, { "step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, when step-in/step-out/step-over leave the current frame, they will continue to step out till they come to a function with " "debug information. Passing a frame argument to step-out will override this option." }, - { "step-avoid-regexp", OptionValue::eTypeRegex , true , REG_EXTENDED, "^std::", NULL, "A regular expression defining functions step-in won't stop in." }, - { "step-avoid-libraries", OptionValue::eTypeFileSpecList , true , REG_EXTENDED, NULL, NULL, "A list of libraries that source stepping won't stop in." }, + { "step-avoid-regexp", OptionValue::eTypeRegex , true , 0, "^std::", NULL, "A regular expression defining functions step-in won't stop in." }, + { "step-avoid-libraries", OptionValue::eTypeFileSpecList , true , 0, NULL, NULL, "A list of libraries that source stepping won't stop in." }, { "trace-thread", OptionValue::eTypeBoolean, false, false, NULL, NULL, "If true, this thread will single-step and log execution." }, { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL } }; @@ -2033,7 +2034,7 @@ Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx) StackFrameSP frame_sp; SymbolContext frame_sc; - if (frame_idx != LLDB_INVALID_INDEX32) + if (frame_idx != LLDB_INVALID_FRAME_ID) { frame_sp = GetStackFrameAtIndex (frame_idx); if (frame_sp) @@ -2043,13 +2044,17 @@ Thread::DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx) } } - const char *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); + const FormatEntity::Entry *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); assert (thread_format); - Debugger::FormatPrompt (thread_format, - frame_sp ? &frame_sc : NULL, - &exe_ctx, - NULL, - strm); + + FormatEntity::Format(*thread_format, + strm, + frame_sp ? &frame_sc : NULL, + &exe_ctx, + NULL, + NULL, + false, + false); } void diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp index d2b039d69f67..0629eb9981ef 100644 --- a/source/Target/ThreadPlanTracer.cpp +++ b/source/Target/ThreadPlanTracer.cpp @@ -212,7 +212,7 @@ ThreadPlanAssemblyTracer::Log () const bool show_bytes = true; const bool show_address = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); - const char *disassemble_format = "${addr-file-or-load}: "; + const FormatEntity::Entry *disassemble_format = m_thread.GetProcess()->GetTarget().GetDebugger().GetDisassemblyFormat(); instruction->Dump (stream, max_opcode_byte_size, show_address, diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp index 16a35b5f5a2f..7f57579c1ee5 100644 --- a/source/Target/UnixSignals.cpp +++ b/source/Target/UnixSignals.cpp @@ -13,7 +13,7 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/StringConvert.h" using namespace lldb_private; @@ -148,7 +148,7 @@ UnixSignals::GetSignalNumberFromName (const char *name) const return pos->first; } - const int32_t signo = Args::StringToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0); + const int32_t signo = StringConvert::ToSInt32(name, LLDB_INVALID_SIGNAL_NUMBER, 0); if (signo != LLDB_INVALID_SIGNAL_NUMBER) return signo; return LLDB_INVALID_SIGNAL_NUMBER; diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp index 161ac6a026f2..a137d365984f 100644 --- a/source/Utility/StringExtractorGDBRemote.cpp +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -265,6 +265,9 @@ StringExtractorGDBRemote::GetServerPacketType () const case 'H': return eServerPacketType_H; + case 'I': + return eServerPacketType_I; + case 'k': if (packet_size == 1) return eServerPacketType_k; break; diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h index e16403c2d154..b51be7d7c28a 100644 --- a/source/Utility/StringExtractorGDBRemote.h +++ b/source/Utility/StringExtractorGDBRemote.h @@ -130,6 +130,7 @@ class StringExtractorGDBRemote : public StringExtractor eServerPacketType_g, eServerPacketType_G, eServerPacketType_H, + eServerPacketType_I, // stdin notification eServerPacketType_k, eServerPacketType_m, eServerPacketType_M, diff --git a/source/Utility/UriParser.cpp b/source/Utility/UriParser.cpp index bf1e601485b4..1d4402feec6e 100644 --- a/source/Utility/UriParser.cpp +++ b/source/Utility/UriParser.cpp @@ -15,6 +15,9 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Host/StringConvert.h" + +using namespace lldb_private; //---------------------------------------------------------------------- // UriParser::Parse @@ -33,17 +36,21 @@ UriParser::Parse(const char* uri, char path_buf[2049] = {'/', 0}; bool ok = false; - if (4==sscanf(uri, "%99[^:/]://%255[^/:]:%[^/]/%2047s", scheme_buf, hostname_buf, port_buf, path_buf+1)) { ok = true; } - else if (3==sscanf(uri, "%99[^:/]://%255[^/:]:%[^/]", scheme_buf, hostname_buf, port_buf)) { ok = true; } + if (4==sscanf(uri, "%99[^:/]://%255[^/:]:%10[^/]/%2047s", scheme_buf, hostname_buf, port_buf, path_buf+1)) { ok = true; } + else if (3==sscanf(uri, "%99[^:/]://%255[^/:]:%10[^/]", scheme_buf, hostname_buf, port_buf)) { ok = true; } else if (3==sscanf(uri, "%99[^:/]://%255[^/]/%2047s", scheme_buf, hostname_buf, path_buf+1)) { ok = true; } else if (2==sscanf(uri, "%99[^:/]://%255[^/]", scheme_buf, hostname_buf)) { ok = true; } - char* end = port_buf; - int port_tmp = strtoul(port_buf, &end, 10); - if (*end != 0) + bool success = false; + int port_tmp = -1; + if (port_buf[0]) { - // there are invalid characters in port_buf - return false; + port_tmp = StringConvert::ToUInt32(port_buf, UINT32_MAX, 10, &success); + if (!success || port_tmp > 65535) + { + // there are invalid characters in port_buf + return false; + } } if (ok) diff --git a/source/Utility/UriParser.h b/source/Utility/UriParser.h index c46628d3bd68..fb129eaf79d5 100644 --- a/source/Utility/UriParser.h +++ b/source/Utility/UriParser.h @@ -20,6 +20,14 @@ class UriParser { public: + // Parses + // RETURN VALUE + // if url is valid, function returns true and + // scheme/hostname/port/path are set to the parsed values + // port it set to -1 if it is not included in the URL + // + // if the url is invalid, function returns false and + // output parameters remain unchanged static bool Parse(const char* uri, std::string& scheme, std::string& hostname, diff --git a/tools/compact-unwind/compact-unwind-dumper.c b/tools/compact-unwind/compact-unwind-dumper.c index fd8ea2161896..0f898dbc76b4 100644 --- a/tools/compact-unwind/compact-unwind-dumper.c +++ b/tools/compact-unwind/compact-unwind-dumper.c @@ -495,7 +495,14 @@ print_encoding_x86_64 (struct baton baton, uint8_t *function_start, uint32_t enc printf ("large stack "); } - printf ("frameless function: stack size %d, register count %d ", stack_size * 8, register_count); + if (mode == UNWIND_X86_64_MODE_STACK_IND) + { + printf ("frameless function: stack size %d, register count %d ", stack_size * 8, register_count); + } + else + { + printf ("frameless function: stack size %d, register count %d ", stack_size, register_count); + } if (register_count == 0) { @@ -591,7 +598,14 @@ print_encoding_x86_64 (struct baton baton, uint8_t *function_start, uint32_t enc } - printf (" CFA is rsp+%d ", stack_size * 8); + if (mode == UNWIND_X86_64_MODE_STACK_IND) + { + printf (" CFA is rsp+%d ", stack_size); + } + else + { + printf (" CFA is rsp+%d ", stack_size * 8); + } uint32_t saved_registers_offset = 1; printf (" rip=[CFA-%d]", saved_registers_offset * 8); @@ -605,24 +619,29 @@ print_encoding_x86_64 (struct baton baton, uint8_t *function_start, uint32_t enc break; case UNWIND_X86_64_REG_RBX: printf (" rbx=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; break; case UNWIND_X86_64_REG_R12: printf (" r12=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; break; case UNWIND_X86_64_REG_R13: printf (" r13=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; break; case UNWIND_X86_64_REG_R14: printf (" r14=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; break; case UNWIND_X86_64_REG_R15: printf (" r15=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; break; case UNWIND_X86_64_REG_RBP: printf (" rbp=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; break; } - saved_registers_offset++; } } @@ -712,7 +731,14 @@ print_encoding_i386 (struct baton baton, uint8_t *function_start, uint32_t encod printf ("large stack "); } - printf ("frameless function: stack size %d, register count %d ", stack_size * 4, register_count); + if (mode == UNWIND_X86_MODE_STACK_IND) + { + printf ("frameless function: stack size %d, register count %d ", stack_size, register_count); + } + else + { + printf ("frameless function: stack size %d, register count %d ", stack_size * 4, register_count); + } if (register_count == 0) { @@ -808,7 +834,14 @@ print_encoding_i386 (struct baton baton, uint8_t *function_start, uint32_t encod } - printf (" CFA is esp+%d ", stack_size * 4); + if (mode == UNWIND_X86_MODE_STACK_IND) + { + printf (" CFA is esp+%d ", stack_size); + } + else + { + printf (" CFA is esp+%d ", stack_size * 4); + } uint32_t saved_registers_offset = 1; printf (" eip=[CFA-%d]", saved_registers_offset * 4); @@ -822,24 +855,29 @@ print_encoding_i386 (struct baton baton, uint8_t *function_start, uint32_t encod break; case UNWIND_X86_REG_EBX: printf (" ebx=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; break; case UNWIND_X86_REG_ECX: printf (" ecx=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; break; case UNWIND_X86_REG_EDX: printf (" edx=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; break; case UNWIND_X86_REG_EDI: printf (" edi=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; break; case UNWIND_X86_REG_ESI: printf (" esi=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; break; case UNWIND_X86_REG_EBP: printf (" ebp=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; break; } - saved_registers_offset++; } } diff --git a/tools/lldb-mi/Driver.cpp b/tools/lldb-mi/Driver.cpp index 34a2471e9672..2a907636723b 100644 --- a/tools/lldb-mi/Driver.cpp +++ b/tools/lldb-mi/Driver.cpp @@ -27,17 +27,17 @@ #ifdef _MSC_VER #include #endif // _MSC_VER -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBCommunication.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBHostOS.h" +#include "lldb/API/SBListener.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBTarget.h" +#include "lldb/API/SBThread.h" +#include "lldb/API/SBProcess.h" using namespace lldb; diff --git a/tools/lldb-mi/Driver.h b/tools/lldb-mi/Driver.h index 41fc21da407e..5bc97383a0c1 100644 --- a/tools/lldb-mi/Driver.h +++ b/tools/lldb-mi/Driver.h @@ -15,17 +15,17 @@ #define lldb_Driver_h_ //#include "Platform.h" // IOR removed -#include +#include "lldb/Utility/PseudoTerminal.h" #include #include #include #include -#include -#include -#include -#include +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBBroadcaster.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBError.h" #include "MIDriverMgr.h" #include "MIDriverBase.h" diff --git a/tools/lldb-mi/MICmdArgValConsume.cpp b/tools/lldb-mi/MICmdArgValConsume.cpp index 3a01db4bc4f8..041005567393 100644 --- a/tools/lldb-mi/MICmdArgValConsume.cpp +++ b/tools/lldb-mi/MICmdArgValConsume.cpp @@ -73,31 +73,22 @@ CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext) if (vwArgContext.IsEmpty()) return MIstatus::success; - if (vwArgContext.GetNumberArgsPresent() == 1) - { - const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); - m_bFound = true; - m_bValid = true; - vwArgContext.RemoveArg(rArg); - return MIstatus::success; - } - - // In reality there are more than one option, if so the file option - // is the last one (don't handle that here - find the best looking one) + // Consume the optional file, line, linenum arguments till the mode '--' argument const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); while (it != vecOptions.end()) { - const CMIUtilString &rTxt(*it); - m_bFound = true; - - if (vwArgContext.RemoveArg(rTxt)) + const CMIUtilString & rTxt( *it ); + + if ( rTxt.compare( "--" ) == 0 ) { + m_bFound = true; m_bValid = true; - return MIstatus::success; - } - else - return MIstatus::success; + return MIstatus::success; + } + + if ( !vwArgContext.RemoveArg( rTxt ) ) + return MIstatus::failure; // Next ++it; diff --git a/tools/lldb-mi/MICmdCmd.h b/tools/lldb-mi/MICmdCmd.h index b51318fa9dff..1fd363084b4a 100644 --- a/tools/lldb-mi/MICmdCmd.h +++ b/tools/lldb-mi/MICmdCmd.h @@ -38,8 +38,8 @@ MI commands implemented are: // Third party headers: #include -#include -#include +#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBCommandReturnObject.h" // In-house headers: #include "MICmdBase.h" diff --git a/tools/lldb-mi/MICmdCmdBreak.cpp b/tools/lldb-mi/MICmdCmdBreak.cpp index c338cf0a363d..9ad7ea3540fd 100644 --- a/tools/lldb-mi/MICmdCmdBreak.cpp +++ b/tools/lldb-mi/MICmdCmdBreak.cpp @@ -25,7 +25,7 @@ //-- // Third Party Headers: -#include +#include "lldb/API/SBBreakpointLocation.h" // In-house headers: #include "MICmdCmdBreak.h" @@ -180,19 +180,16 @@ CMICmdCmdBreakInsert::Execute(void) CMIUtilString fileName; MIuint nFileLine = 0; CMIUtilString strFileFn; - const MIint nPosColon = m_brkName.find(cColon); - if (nPosColon != (MIint)std::string::npos) + CMIUtilString rStrLineOrFn; + // Full path in windows can have : after drive letter. So look for the + // last colon + const size_t nPosColon = m_brkName.find_last_of(cColon); + if (nPosColon != std::string::npos) { - CMIUtilString::VecString_t vecFileAndLocation; - const MIuint nSplits = m_brkName.Split(cColon, vecFileAndLocation); - MIunused(nSplits); - if (vecFileAndLocation.size() != 2) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); - return MIstatus::failure; - } - fileName = vecFileAndLocation.at(0); - const CMIUtilString &rStrLineOrFn(vecFileAndLocation.at(1)); + // extract file name and line number from it + fileName = m_brkName.substr(0, nPosColon); + rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1); + if (rStrLineOrFn.empty()) eBrkPtType = eBreakPoint_ByName; else @@ -232,20 +229,20 @@ CMICmdCmdBreakInsert::Execute(void) // Ask LLDB to create a breakpoint bool bOk = MIstatus::success; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); switch (eBrkPtType) { case eBreakPoint_ByAddress: - m_brkPt = rTarget.BreakpointCreateByAddress(nAddress); + m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress); break; case eBreakPoint_ByFileFn: - m_brkPt = rTarget.BreakpointCreateByName(strFileFn.c_str(), fileName.c_str()); + m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), fileName.c_str()); break; case eBreakPoint_ByFileLine: - m_brkPt = rTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); + m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); break; case eBreakPoint_ByName: - m_brkPt = rTarget.BreakpointCreateByName(m_brkName.c_str(), rTarget.GetExecutable().GetFilename()); + m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), sbTarget.GetExecutable().GetFilename()); break; case eBreakPoint_count: case eBreakPoint_NotDefineYet: @@ -327,7 +324,7 @@ CMICmdCmdBreakInsert::Acknowledge(void) sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; - sBrkPtInfo.m_nTimes = m_brkPt.GetNumLocations(); + sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount(); sBrkPtInfo.m_strOrigLoc = m_brkName; sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; sBrkPtInfo.m_bPending = m_bBrkPtIsPending; @@ -440,7 +437,7 @@ CMICmdCmdBreakDelete::Execute(void) } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const bool bBrkPt = rSessionInfo.m_lldbTarget.BreakpointDelete(static_cast(nBrk)); + const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(static_cast(nBrk)); if (!bBrkPt) { const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk)); @@ -560,7 +557,7 @@ CMICmdCmdBreakDisable::Execute(void) } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(nBrk)); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast(nBrk)); if (brkPt.IsValid()) { m_bBrkPtDisabledOk = true; @@ -700,7 +697,7 @@ CMICmdCmdBreakEnable::Execute(void) } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(nBrk)); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast(nBrk)); if (brkPt.IsValid()) { m_bBrkPtEnabledOk = true; @@ -837,7 +834,7 @@ CMICmdCmdBreakAfter::Execute(void) m_nBrkPtCount = pArgCount->GetValue(); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(m_nBrkPtId)); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast(m_nBrkPtId)); if (brkPt.IsValid()) { brkPt.SetIgnoreCount(m_nBrkPtCount); @@ -972,7 +969,7 @@ CMICmdCmdBreakCondition::Execute(void) m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID(static_cast(m_nBrkPtId)); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast(m_nBrkPtId)); if (brkPt.IsValid()) { brkPt.SetCondition(m_strBrkPtExpr.c_str()); diff --git a/tools/lldb-mi/MICmdCmdBreak.h b/tools/lldb-mi/MICmdCmdBreak.h index c9540b0521eb..371afa15b639 100644 --- a/tools/lldb-mi/MICmdCmdBreak.h +++ b/tools/lldb-mi/MICmdCmdBreak.h @@ -36,7 +36,7 @@ #pragma once // Third party headers: -#include +#include "lldb/API/SBBreakpoint.h" // In-house headers: #include "MICmdBase.h" diff --git a/tools/lldb-mi/MICmdCmdData.cpp b/tools/lldb-mi/MICmdCmdData.cpp index e1abe83b9165..92e419073335 100644 --- a/tools/lldb-mi/MICmdCmdData.cpp +++ b/tools/lldb-mi/MICmdCmdData.cpp @@ -28,10 +28,10 @@ //-- // Third Party Headers: -#include -#include -#include -#include +#include "lldb/API/SBThread.h" +#include "lldb/API/SBInstruction.h" +#include "lldb/API/SBInstructionList.h" +#include "lldb/API/SBStream.h" // In-house headers: #include "MICmdCmdData.h" @@ -122,22 +122,22 @@ CMICmdCmdDataEvaluateExpression::Execute(void) const CMIUtilString &rExpression(pArgExpr->GetValue()); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); m_bExpressionValid = (thread.GetNumFrames() > 0); if (!m_bExpressionValid) return MIstatus::success; lldb::SBFrame frame = thread.GetSelectedFrame(); lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str()); - if (!value.IsValid()) + if (!value.IsValid() || value.GetError().Fail()) value = frame.FindVariable(rExpression.c_str()); - if (!value.IsValid()) + const CMICmnLLDBUtilSBValue utilValue(value); + if (!utilValue.IsValid() || utilValue.IsValueUnknown()) { m_bEvaluatedExpression = false; return MIstatus::success; } - const CMICmnLLDBUtilSBValue utilValue(value); if (!utilValue.HasName()) { if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar)) @@ -279,16 +279,10 @@ CMICmdCmdDataEvaluateExpression::CreateSelf(void) bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, MIchar &vrwInvalidChar) { - bool bFoundInvalidCharInExpression = false; - vrwInvalidChar = 0x00; - - if (vrExpr.at(0) == '\\') - { - // Example: Mouse hover over "%5d" expression has \"%5d\" in it - bFoundInvalidCharInExpression = true; - vrwInvalidChar = '\\'; - } - + static const std::string strInvalidCharacters(";#\\"); + const size_t nInvalidCharacterOffset = vrExpr.find_first_of(strInvalidCharacters); + const bool bFoundInvalidCharInExpression = (nInvalidCharacterOffset != CMIUtilString::npos); + vrwInvalidChar = bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00; return bFoundInvalidCharInExpression; } @@ -342,7 +336,7 @@ bool CMICmdCmdDataDisassemble::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1))); @@ -373,7 +367,7 @@ CMICmdCmdDataDisassemble::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; @@ -410,23 +404,24 @@ CMICmdCmdDataDisassemble::Execute(void) const MIuint nDisasmMode = pArgMode->GetValue(); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); lldb::addr_t lldbStartAddr = static_cast(nAddrStart); - lldb::SBInstructionList instructions = rTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, rTarget), nAddrEnd - nAddrStart); + lldb::SBInstructionList instructions = sbTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart); const MIuint nInstructions = instructions.GetSize(); for (size_t i = 0; i < nInstructions; i++) { const MIchar *pUnknown = "??"; lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i); - const MIchar *pStrMnemonic = instrt.GetMnemonic(rTarget); + const MIchar *pStrMnemonic = instrt.GetMnemonic(sbTarget); pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; lldb::SBAddress address = instrt.GetAddress(); - lldb::addr_t addr = address.GetLoadAddress(rTarget); + lldb::addr_t addr = address.GetLoadAddress(sbTarget); const MIchar *pFnName = address.GetFunction().GetName(); pFnName = (pFnName != nullptr) ? pFnName : pUnknown; lldb::addr_t addrOffSet = address.GetOffset(); - const MIchar *pStrOperands = instrt.GetOperands(rTarget); + const MIchar *pStrOperands = instrt.GetOperands(sbTarget); pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; + const size_t instrtSize = instrt.GetByteSize(); // MI "{address=\"0x%08llx\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%08llx", addr)); @@ -438,9 +433,12 @@ CMICmdCmdDataDisassemble::Execute(void) const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%lld", addrOffSet)); const CMICmnMIValueResult miValueResult3("offset", miValueConst3); miValueTuple.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%s %s", pStrMnemonic, pStrOperands)); - const CMICmnMIValueResult miValueResult4("inst", miValueConst4); + const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", instrtSize)); + const CMICmnMIValueResult miValueResult4("size", miValueConst4); miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5(CMIUtilString::Format("%s %s", pStrMnemonic, pStrOperands)); + const CMICmnMIValueResult miValueResult5("inst", miValueConst5); + miValueTuple.Add(miValueResult5); if (nDisasmMode == 1) { @@ -599,9 +597,9 @@ CMICmdCmdDataReadMemoryBytes::Execute(void) } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); lldb::SBError error; - const MIuint64 nReadBytes = rProcess.ReadMemory(static_cast(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error); + const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error); if (nReadBytes != nAddrNumBytes) { SetError( @@ -826,30 +824,58 @@ CMICmdCmdDataListRegisterNames::ParseArgs(void) bool CMICmdCmdDataListRegisterNames::Execute(void) { + CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - if (!rProcess.IsValid()) + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } - lldb::SBThread thread = rProcess.GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - for (MIuint i = 0; i < nRegisters; i++) + const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); + if (!rVecRegNo.empty()) { - lldb::SBValue value = registers.GetValueAtIndex(i); - const MIuint nRegChildren = value.GetNumChildren(); - for (MIuint j = 0; j < nRegChildren; j++) + // List of required registers + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); + while (it != rVecRegNo.end()) { - lldb::SBValue value2 = value.GetChildAtIndex(j); - if (value2.IsValid()) + const CMICmdArgValNumber *pRegNo = static_cast(*it); + const MIuint nRegIndex = pRegNo->GetValue(); + lldb::SBValue regValue = GetRegister(nRegIndex); + if (regValue.IsValid()) { - const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(value2).GetName()); + const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName()); m_miValueList.Add(miValueConst); } + + // Next + ++it; + } + } + else + { + // List of all registers + lldb::SBThread thread = sbProcess.GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + for (MIuint i = 0; i < nRegisters; i++) + { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + for (MIuint j = 0; j < nRegChildren; j++) + { + lldb::SBValue regValue = value.GetChildAtIndex(j); + if (regValue.IsValid()) + { + const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName()); + const bool bOk = m_miValueList.Add(miValueConst); + if (!bOk) + return MIstatus::failure; + } + } } } @@ -889,6 +915,42 @@ CMICmdCmdDataListRegisterNames::CreateSelf(void) return new CMICmdCmdDataListRegisterNames(); } +//++ ------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The factory +// calls this function to create an instance of *this command. +// Type: Method. +// Args: None. +// Return: lldb::SBValue - LLDB SBValue object. +// Throws: None. +//-- +lldb::SBValue +CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const +{ + lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + MIuint nRegisterIndex(vRegisterIndex); + for (MIuint i = 0; i < nRegisters; i++) + { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + if (nRegisterIndex >= nRegChildren) + { + nRegisterIndex -= nRegChildren; + continue; + } + + lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); + if (value2.IsValid()) + { + return value2; + } + } + + return lldb::SBValue(); +} + //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- @@ -906,7 +968,6 @@ CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues(void) , m_constStrArgFormat("fmt") , m_constStrArgRegNo("regno") , m_miValueList(true) - , m_pProcess(nullptr) { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "data-list-register-values"; @@ -975,33 +1036,60 @@ CMICmdCmdDataListRegisterValues::Execute(void) } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - if (!rProcess.IsValid()) + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } - m_pProcess = &rProcess; const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); - while (it != rVecRegNo.end()) + if (!rVecRegNo.empty()) { - const CMICmdArgValNumber *pRegNo = static_cast(*it); - const MIuint nReg = pRegNo->GetValue(); - lldb::SBValue regValue = GetRegister(nReg); - const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(regValue, eFormat)); + // List of required registers + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); + while (it != rVecRegNo.end()) + { + const CMICmdArgValNumber *pRegNo = static_cast(*it); + const MIuint nRegIndex = pRegNo->GetValue(); + lldb::SBValue regValue = GetRegister(nRegIndex); + if (regValue.IsValid()) + { + const bool bOk = AddToOutput(nRegIndex, regValue, eFormat); + if (!bOk) + return MIstatus::failure; + } - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", nReg)); - const CMICmnMIValueResult miValueResult("number", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueConst miValueConst2(strRegValue); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); - m_miValueList.Add(miValueTuple); + // Next + ++it; + } + } + else + { + // No register numbers are provided. Output all registers. + lldb::SBThread thread = sbProcess.GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + MIuint nRegIndex = 0; + for (MIuint i = 0; i < nRegisters; i++) + { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + for (MIuint j = 0; j < nRegChildren; j++) + { + lldb::SBValue regValue = value.GetChildAtIndex(j); + if (regValue.IsValid()) + { + const bool bOk = AddToOutput(nRegIndex, regValue, eFormat); + if (!bOk) + return MIstatus::failure; + } - // Next - ++it; + // Next + ++nRegIndex; + } + } } return MIstatus::success; @@ -1051,27 +1139,52 @@ CMICmdCmdDataListRegisterValues::CreateSelf(void) lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const { - lldb::SBThread thread = m_pProcess->GetSelectedThread(); + lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); lldb::SBFrame frame = thread.GetSelectedFrame(); lldb::SBValueList registers = frame.GetRegisters(); const MIuint nRegisters = registers.GetSize(); + MIuint nRegisterIndex(vRegisterIndex); for (MIuint i = 0; i < nRegisters; i++) { lldb::SBValue value = registers.GetValueAtIndex(i); const MIuint nRegChildren = value.GetNumChildren(); - if (nRegChildren > 0) + if (nRegisterIndex >= nRegChildren) { - lldb::SBValue value2 = value.GetChildAtIndex(vRegisterIndex); - if (value2.IsValid()) - { - return value2; - } + nRegisterIndex -= nRegChildren; + continue; + } + + lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); + if (value2.IsValid()) + { + return value2; } } return lldb::SBValue(); } +//++ ------------------------------------------------------------------------------------ +// Details: Adds the register value to the output list. +// Type: Method. +// Args: Value of the register, its index and output format. +// Return: None +// Throws: None. +//-- +bool +CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, + CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) +{ + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, veVarFormat)); + const CMICmnMIValueConst miValueConst2(strRegValue); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + bool bOk = miValueTuple.Add(miValueResult2); + return bOk && m_miValueList.Add(miValueTuple); +} + //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- @@ -1371,10 +1484,10 @@ CMICmdCmdDataWriteMemory::Execute(void) *m_pBufferMemory = static_cast(nValue); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); lldb::SBError error; lldb::addr_t addr = static_cast(m_nAddr + nAddrOffset); - const size_t nBytesWritten = rProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); + const size_t nBytesWritten = sbProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); if (nBytesWritten != static_cast(m_nCount)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), m_cmdData.strMiCmd.c_str(), m_nCount, addr)); diff --git a/tools/lldb-mi/MICmdCmdData.h b/tools/lldb-mi/MICmdCmdData.h index 74ceeb8581b9..5084beea6d8f 100644 --- a/tools/lldb-mi/MICmdCmdData.h +++ b/tools/lldb-mi/MICmdCmdData.h @@ -42,6 +42,7 @@ #include "MICmdBase.h" #include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnLLDBDebugSessionInfoVarObj.h" //++ ============================================================================ // Details: MI command class. MI commands derived from the command base class. @@ -218,6 +219,10 @@ class CMICmdCmdDataListRegisterNames : public CMICmdBase // From CMICmnBase /* dtor */ virtual ~CMICmdCmdDataListRegisterNames(void); + // Methods: + private: + lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; + // Attributes: private: const CMIUtilString m_constStrArgThreadGroup; // Not specified in MI spec but Eclipse gives this option @@ -255,6 +260,7 @@ class CMICmdCmdDataListRegisterValues : public CMICmdBase // Methods: private: lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; + bool AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat); // Attributes: private: @@ -263,7 +269,6 @@ class CMICmdCmdDataListRegisterValues : public CMICmdBase const CMIUtilString m_constStrArgFormat; const CMIUtilString m_constStrArgRegNo; CMICmnMIValueList m_miValueList; - lldb::SBProcess *m_pProcess; }; //++ ============================================================================ diff --git a/tools/lldb-mi/MICmdCmdExec.cpp b/tools/lldb-mi/MICmdCmdExec.cpp index 9e1224363f5d..eec62c8d37e8 100644 --- a/tools/lldb-mi/MICmdCmdExec.cpp +++ b/tools/lldb-mi/MICmdCmdExec.cpp @@ -27,9 +27,9 @@ //-- // Third Party Headers: -#include -#include -#include +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBStream.h" #include "lldb/lldb-enumerations.h" // In-house headers: @@ -91,8 +91,8 @@ CMICmdCmdExecRun::Execute(void) lldb::SBError error; lldb::SBStream errMsg; uint32_t launch_flags = lldb::LaunchFlags::eLaunchFlagDebug; - lldb::SBProcess process = rSessionInfo.m_lldbTarget.Launch(rSessionInfo.m_rLlldbListener, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, launch_flags, false, error); + lldb::SBProcess process = rSessionInfo.GetTarget().Launch(rSessionInfo.GetListener(), nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, launch_flags, false, error); if ((!process.IsValid()) || (error.Fail())) { @@ -100,9 +100,6 @@ CMICmdCmdExecRun::Execute(void) return MIstatus::failure; } - // Save the process in the session info - rSessionInfo.m_lldbProcess = process; - if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); @@ -137,7 +134,7 @@ CMICmdCmdExecRun::Acknowledge(void) m_miResultRecord = miRecordResult; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); // Give the client '=thread-group-started,id="i1" pid="xyz"' m_bHasResultRecordExtra = true; const CMICmnMIValueConst miValueConst2("i1"); @@ -212,7 +209,7 @@ CMICmdCmdExecContinue::Execute(void) { const MIchar *pCmd = "continue"; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand(pCmd, m_lldbResult); + const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(pCmd, m_lldbResult); MIunused(rtn); if (m_lldbResult.GetErrorSize() == 0) @@ -328,7 +325,7 @@ bool CMICmdCmdExecNext::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); return (bOk && ParseValidateCmdOptions()); } @@ -349,14 +346,14 @@ CMICmdCmdExecNext::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-over"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); @@ -455,7 +452,7 @@ bool CMICmdCmdExecStep::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); return (bOk && ParseValidateCmdOptions()); } @@ -476,14 +473,14 @@ CMICmdCmdExecStep::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-in"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); @@ -582,7 +579,7 @@ bool CMICmdCmdExecNextInstruction::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); return (bOk && ParseValidateCmdOptions()); } @@ -603,14 +600,14 @@ CMICmdCmdExecNextInstruction::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-inst-over"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); @@ -709,7 +706,7 @@ bool CMICmdCmdExecStepInstruction::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumber, false, false))); return (bOk && ParseValidateCmdOptions()); } @@ -730,14 +727,14 @@ CMICmdCmdExecStepInstruction::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-inst"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); @@ -836,7 +833,7 @@ bool CMICmdCmdExecFinish::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, false, CMICmdArgValListBase::eArgValType_Number, 1))); return (bOk && ParseValidateCmdOptions()); @@ -858,14 +855,14 @@ CMICmdCmdExecFinish::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-out"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); @@ -962,7 +959,7 @@ bool CMICmdCmdExecInterrupt::Execute(void) { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("process interrupt"); const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); MIunused(status); diff --git a/tools/lldb-mi/MICmdCmdExec.h b/tools/lldb-mi/MICmdCmdExec.h index cf59ec4f5b3e..be03d6b93566 100644 --- a/tools/lldb-mi/MICmdCmdExec.h +++ b/tools/lldb-mi/MICmdCmdExec.h @@ -38,7 +38,7 @@ #pragma once // Third party headers: -#include +#include "lldb/API/SBCommandReturnObject.h" // In-house headers: #include "MICmdBase.h" diff --git a/tools/lldb-mi/MICmdCmdFile.cpp b/tools/lldb-mi/MICmdCmdFile.cpp index a954f88dac11..83862f24f1f1 100644 --- a/tools/lldb-mi/MICmdCmdFile.cpp +++ b/tools/lldb-mi/MICmdCmdFile.cpp @@ -20,7 +20,7 @@ //-- // Third Party Headers: -#include +#include "lldb/API/SBStream.h" // In-house headers: #include "MICmdCmdFile.h" @@ -96,7 +96,7 @@ CMICmdCmdFileExecAndSymbols::Execute(void) CMICmdArgValFile *pArgFile = static_cast(pArgNamedFile); const CMIUtilString &strExeFilePath(pArgFile->GetValue()); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDbgr = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); lldb::SBError error; const MIchar *pTargetTriple = nullptr; // Let LLDB discover the triple required const MIchar *pTargetPlatformName = ""; @@ -137,8 +137,6 @@ CMICmdCmdFileExecAndSymbols::Execute(void) return MIstatus::failure; } - rSessionInfo.m_lldbTarget = target; - return MIstatus::success; } diff --git a/tools/lldb-mi/MICmdCmdGdbInfo.cpp b/tools/lldb-mi/MICmdCmdGdbInfo.cpp index dde6a0b40135..be70962b63ae 100644 --- a/tools/lldb-mi/MICmdCmdGdbInfo.cpp +++ b/tools/lldb-mi/MICmdCmdGdbInfo.cpp @@ -20,7 +20,7 @@ //-- // Third party headers: -#include +#include "lldb/API/SBCommandReturnObject.h" // In-house headers: #include "MICmdCmdGdbInfo.h" @@ -198,11 +198,11 @@ CMICmdCmdGdbInfo::PrintFnSharedLibrary(void) bool bOk = rStdout.TextToStdout("~\"From To Syms Read Shared Object Library\""); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; - const MIuint nModules = rTarget.GetNumModules(); + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); + const MIuint nModules = sbTarget.GetNumModules(); for (MIuint i = 0; bOk && (i < nModules); i++) { - lldb::SBModule module = rTarget.GetModuleAtIndex(i); + lldb::SBModule module = sbTarget.GetModuleAtIndex(i); if (module.IsValid()) { const CMIUtilString strModuleFilePath(module.GetFileSpec().GetDirectory()); @@ -216,7 +216,7 @@ CMICmdCmdGdbInfo::PrintFnSharedLibrary(void) for (MIuint j = 0; j < nSections; j++) { lldb::SBSection section = module.GetSectionAtIndex(j); - lldb::addr_t addrLoad = section.GetLoadAddress(rTarget); + lldb::addr_t addrLoad = section.GetLoadAddress(sbTarget); if (addrLoad != (lldb::addr_t) - 1) { if (!bHaveAddrLoad) diff --git a/tools/lldb-mi/MICmdCmdMiscellanous.cpp b/tools/lldb-mi/MICmdCmdMiscellanous.cpp index 6b863a8ea8db..4e4e1b986e8a 100644 --- a/tools/lldb-mi/MICmdCmdMiscellanous.cpp +++ b/tools/lldb-mi/MICmdCmdMiscellanous.cpp @@ -23,8 +23,8 @@ //-- // Third Party Headers: -#include -#include +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBThread.h" // In-house headers: #include "MICmdCmdMiscellanous.h" @@ -84,7 +84,7 @@ bool CMICmdCmdGdbExit::Execute(void) { CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true); - const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.m_lldbProcess.Detach(); + const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.GetProcess().Detach(); // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid() return MIstatus::success; @@ -234,17 +234,17 @@ CMICmdCmdListThreadGroups::Execute(void) m_bIsI1 = true; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - // Note do not check for rProcess is IsValid(), continue + // Note do not check for sbProcess is IsValid(), continue m_vecMIValueTuple.clear(); - const MIuint nThreads = rProcess.GetNumThreads(); + const MIuint nThreads = sbProcess.GetNumThreads(); for (MIuint i = 0; i < nThreads; i++) { // GetThreadAtIndex() uses a base 0 index // GetThreadByIndexID() uses a base 1 index - lldb::SBThread thread = rProcess.GetThreadAtIndex(i); + lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); if (thread.IsValid()) { @@ -292,9 +292,9 @@ CMICmdCmdListThreadGroups::Acknowledge(void) miTuple.Add(miValueResult2); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - if (rSessionInfo.m_lldbProcess.IsValid()) + if (rSessionInfo.GetProcess().IsValid()) { - const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); const CMICmnMIValueConst miValueConst3(strPid); const CMICmnMIValueResult miValueResult3("pid", miValueConst3); @@ -328,20 +328,20 @@ CMICmdCmdListThreadGroups::Acknowledge(void) miTuple.Add(miValueResult2); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - if (rSessionInfo.m_lldbProcess.IsValid()) + if (rSessionInfo.GetProcess().IsValid()) { - const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); const CMICmnMIValueConst miValueConst3(strPid); const CMICmnMIValueResult miValueResult3("pid", miValueConst3); miTuple.Add(miValueResult3); } - if (rSessionInfo.m_lldbTarget.IsValid()) + if (rSessionInfo.GetTarget().IsValid()) { - lldb::SBTarget &rTrgt = rSessionInfo.m_lldbTarget; - const MIchar *pDir = rTrgt.GetExecutable().GetDirectory(); - const MIchar *pFileName = rTrgt.GetExecutable().GetFilename(); + lldb::SBTarget sbTrgt = rSessionInfo.GetTarget(); + const MIchar *pDir = sbTrgt.GetExecutable().GetDirectory(); + const MIchar *pFileName = sbTrgt.GetExecutable().GetFilename(); const CMIUtilString strFile(CMIUtilString::Format("%s/%s", pDir, pFileName)); const CMICmnMIValueConst miValueConst4(strFile); const CMICmnMIValueResult miValueResult4("executable", miValueConst4); @@ -470,7 +470,7 @@ CMICmdCmdInterpreterExec::Execute(void) const CMIUtilString &rStrCommand(pArgCommand->GetValue()); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); const lldb::ReturnStatus rtn = - rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand(rStrCommand.c_str(), m_lldbResult, true); + rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(rStrCommand.c_str(), m_lldbResult, true); MIunused(rtn); return MIstatus::success; @@ -588,7 +588,7 @@ CMICmdCmdInferiorTtySet::Execute(void) bool CMICmdCmdInferiorTtySet::Acknowledge(void) { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error); m_miResultRecord = miRecordResult; return MIstatus::success; diff --git a/tools/lldb-mi/MICmdCmdMiscellanous.h b/tools/lldb-mi/MICmdCmdMiscellanous.h index 1cabbac7e80a..fd990940e44d 100644 --- a/tools/lldb-mi/MICmdCmdMiscellanous.h +++ b/tools/lldb-mi/MICmdCmdMiscellanous.h @@ -34,7 +34,7 @@ #pragma once // Third party headers: -#include +#include "lldb/API/SBCommandReturnObject.h" // In-house headers: #include "MICmdBase.h" diff --git a/tools/lldb-mi/MICmdCmdStack.cpp b/tools/lldb-mi/MICmdCmdStack.cpp index 4ed6803a1edb..4ab7164a30b7 100644 --- a/tools/lldb-mi/MICmdCmdStack.cpp +++ b/tools/lldb-mi/MICmdCmdStack.cpp @@ -23,7 +23,7 @@ //-- // Third Party Headers: -#include +#include "lldb/API/SBThread.h" // In-house headers: #include "MICmdCmdStack.h" @@ -82,7 +82,7 @@ bool CMICmdCmdStackInfoDepth::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false))); return (bOk && ParseValidateCmdOptions()); } @@ -104,15 +104,15 @@ CMICmdCmdStackInfoDepth::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); m_nThreadFrames = thread.GetNumFrames(); return MIstatus::success; @@ -202,7 +202,7 @@ bool CMICmdCmdStackListFrames::ParseArgs(void) { bool bOk = - m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, true, true, CMICmdArgValListBase::eArgValType_Number, 1))); + m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true))); return (bOk && ParseValidateCmdOptions()); @@ -226,7 +226,7 @@ CMICmdCmdStackListFrames::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; @@ -237,8 +237,8 @@ CMICmdCmdStackListFrames::Execute(void) const MIuint nFrameLow = pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); MIuint nThreadFrames = thread.GetNumFrames(); // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in the min calc as the arg @@ -350,6 +350,9 @@ CMICmdCmdStackListArguments::CMICmdCmdStackListArguments(void) , m_miValueList(true) , m_constStrArgThread("thread") , m_constStrArgPrintValues("print-values") + , m_constStrArgNoValues("no-values") + , m_constStrArgAllValues("all-values") + , m_constStrArgSimpleValues("simple-values") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "stack-list-arguments"; @@ -383,7 +386,10 @@ CMICmdCmdStackListArguments::ParseArgs(void) { bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); - bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, true, false))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgNoValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgAllValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgSimpleValues, false, true))); return (bOk && ParseValidateCmdOptions()); } @@ -401,6 +407,9 @@ CMICmdCmdStackListArguments::Execute(void) { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); CMICMDBASE_GETOPTION(pArgPrintValues, Number, m_constStrArgPrintValues); + CMICMDBASE_GETOPTION(pArgNoValues, OptionLong, m_constStrArgNoValues); + CMICMDBASE_GETOPTION(pArgAllValues, OptionLong, m_constStrArgAllValues); + CMICMDBASE_GETOPTION(pArgSimpleValues, OptionLong, m_constStrArgSimpleValues); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; @@ -413,9 +422,32 @@ CMICmdCmdStackListArguments::Execute(void) } } + CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat; + if (pArgPrintValues->GetFound()) + { + const MIuint nPrintValues = pArgPrintValues->GetValue(); + if (nPrintValues >= CMICmnLLDBDebugSessionInfo::kNumVariableInfoFormats) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + eVarInfoFormat = static_cast(nPrintValues); + } + else if (pArgNoValues->GetFound()) + eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; + else if (pArgAllValues->GetFound()) + eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues; + else if (pArgSimpleValues->GetFound()) + eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues; + else + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); m_bThreadInvalid = !thread.IsValid(); if (m_bThreadInvalid) return MIstatus::success; @@ -433,7 +465,7 @@ CMICmdCmdStackListArguments::Execute(void) lldb::SBFrame frame = thread.GetFrameAtIndex(i); CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; - if (!rSessionInfo.MIResponseFormVariableInfo3(frame, maskVarTypes, miValueList)) + if (!rSessionInfo.MIResponseFormVariableInfo3(frame, maskVarTypes, eVarInfoFormat, miValueList)) return MIstatus::failure; const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i)); const CMICmnMIValueResult miValueResult("level", miValueConst); @@ -508,6 +540,9 @@ CMICmdCmdStackListLocals::CMICmdCmdStackListLocals(void) , m_constStrArgThread("thread") , m_constStrArgFrame("frame") , m_constStrArgPrintValues("print-values") + , m_constStrArgNoValues("no-values") + , m_constStrArgAllValues("all-values") + , m_constStrArgSimpleValues("simple-values") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "stack-list-locals"; @@ -543,7 +578,10 @@ CMICmdCmdStackListLocals::ParseArgs(void) m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); - bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, true, false))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgNoValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgAllValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgSimpleValues, false, true))); return (bOk && ParseValidateCmdOptions()); } @@ -561,6 +599,10 @@ CMICmdCmdStackListLocals::Execute(void) { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + CMICMDBASE_GETOPTION(pArgPrintValues, Number, m_constStrArgPrintValues); + CMICMDBASE_GETOPTION(pArgNoValues, OptionLong, m_constStrArgNoValues); + CMICMDBASE_GETOPTION(pArgAllValues, OptionLong, m_constStrArgAllValues); + CMICMDBASE_GETOPTION(pArgSimpleValues, OptionLong, m_constStrArgSimpleValues); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; @@ -572,6 +614,7 @@ CMICmdCmdStackListLocals::Execute(void) return MIstatus::failure; } } + MIuint64 nFrame = UINT64_MAX; if (pArgFrame->GetFound()) { @@ -582,9 +625,32 @@ CMICmdCmdStackListLocals::Execute(void) } } + CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat; + if (pArgPrintValues->GetFound()) + { + const MIuint nPrintValues = pArgPrintValues->GetValue(); + if (nPrintValues >= CMICmnLLDBDebugSessionInfo::kNumVariableInfoFormats) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + eVarInfoFormat = static_cast(nPrintValues); + } + else if (pArgNoValues->GetFound()) + eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; + else if (pArgAllValues->GetFound()) + eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues; + else if (pArgSimpleValues->GetFound()) + eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues; + else + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID(nThreadId) : rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); m_bThreadInvalid = !thread.IsValid(); if (m_bThreadInvalid) return MIstatus::success; @@ -596,12 +662,11 @@ CMICmdCmdStackListLocals::Execute(void) return MIstatus::success; } - const MIuint nFrames = thread.GetNumFrames(); - MIunused(nFrames); lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); + CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals; - if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, miValueList)) + if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList)) return MIstatus::failure; m_miValueList = miValueList; diff --git a/tools/lldb-mi/MICmdCmdStack.h b/tools/lldb-mi/MICmdCmdStack.h index bae43dceed6d..ebef7e197f5f 100644 --- a/tools/lldb-mi/MICmdCmdStack.h +++ b/tools/lldb-mi/MICmdCmdStack.h @@ -143,7 +143,10 @@ class CMICmdCmdStackListArguments : public CMICmdBase bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid CMICmnMIValueList m_miValueList; const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + const CMIUtilString m_constStrArgPrintValues; + const CMIUtilString m_constStrArgNoValues; + const CMIUtilString m_constStrArgAllValues; + const CMIUtilString m_constStrArgSimpleValues; }; //++ ============================================================================ @@ -179,5 +182,8 @@ class CMICmdCmdStackListLocals : public CMICmdBase CMICmnMIValueList m_miValueList; const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option const CMIUtilString m_constStrArgFrame; // Not specified in MI spec but Eclipse gives this option - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + const CMIUtilString m_constStrArgPrintValues; + const CMIUtilString m_constStrArgNoValues; + const CMIUtilString m_constStrArgAllValues; + const CMIUtilString m_constStrArgSimpleValues; }; diff --git a/tools/lldb-mi/MICmdCmdTarget.cpp b/tools/lldb-mi/MICmdCmdTarget.cpp index ec19493af33b..c3ef0b44e806 100644 --- a/tools/lldb-mi/MICmdCmdTarget.cpp +++ b/tools/lldb-mi/MICmdCmdTarget.cpp @@ -20,9 +20,9 @@ //-- // Third Party Headers: -#include -#include -#include +#include "lldb/API/SBStream.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" // In-house headers: #include "MICmdCmdTarget.h" @@ -100,7 +100,7 @@ CMICmdCmdTargetSelect::Execute(void) // Check we have a valid target // Note: target created via 'file-exec-and-symbols' command - if (!rSessionInfo.m_lldbTarget.IsValid()) + if (!rSessionInfo.GetTarget().IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; @@ -120,7 +120,7 @@ CMICmdCmdTargetSelect::Execute(void) // Ask LLDB to collect to the target port const MIchar *pPlugin("gdb-remote"); lldb::SBError error; - lldb::SBProcess process = rSessionInfo.m_lldbTarget.ConnectRemote(rSessionInfo.m_rLlldbListener, strUrl.c_str(), pPlugin, error); + lldb::SBProcess process = rSessionInfo.GetTarget().ConnectRemote(rSessionInfo.GetListener(), strUrl.c_str(), pPlugin, error); // Verify that we have managed to connect successfully lldb::SBStream errMsg; @@ -135,16 +135,11 @@ CMICmdCmdTargetSelect::Execute(void) return MIstatus::failure; } - // Save the process in the session info - // Note: Order is important here since this process handle may be used by CMICmnLLDBDebugHandleEvents - // which can fire when interpreting via HandleCommand() below. - rSessionInfo.m_lldbProcess = process; - // Set the environment path if we were given one CMIUtilString strWkDir; if (rSessionInfo.SharedDataRetrieve(rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) { - lldb::SBDebugger &rDbgr = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); @@ -156,7 +151,7 @@ CMICmdCmdTargetSelect::Execute(void) CMIUtilString strSolibPath; if (rSessionInfo.SharedDataRetrieve(rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath)) { - lldb::SBDebugger &rDbgr = rSessionInfo.m_rLldbDebugger; + lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter(); CMIUtilString strCmdString = CMIUtilString::Format("target modules search-paths add . %s", strSolibPath.c_str()); @@ -190,7 +185,7 @@ CMICmdCmdTargetSelect::Acknowledge(void) m_miResultRecord = miRecordResult; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); + lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger // Give the client '=thread-group-started,id="i1"' m_bHasResultRecordExtra = true; diff --git a/tools/lldb-mi/MICmdCmdThread.cpp b/tools/lldb-mi/MICmdCmdThread.cpp index 3a448a777008..52fd96050632 100644 --- a/tools/lldb-mi/MICmdCmdThread.cpp +++ b/tools/lldb-mi/MICmdCmdThread.cpp @@ -20,8 +20,8 @@ //-- // Third Party Headers: -#include -#include +#include "lldb/API/SBBreakpointLocation.h" +#include "lldb/API/SBThread.h" // In-house headers: #include "MICmdCmdThread.h" @@ -99,12 +99,12 @@ CMICmdCmdThreadInfo::Execute(void) } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); if (m_bSingleThread) { - thread = rProcess.GetThreadByIndexID(nThreadId); + thread = sbProcess.GetThreadByIndexID(nThreadId); m_bThreadInvalid = thread.IsValid(); if (!m_bThreadInvalid) return MIstatus::success; @@ -120,10 +120,10 @@ CMICmdCmdThreadInfo::Execute(void) // Multiple threads m_vecMIValueTuple.clear(); - const MIuint nThreads = rProcess.GetNumThreads(); + const MIuint nThreads = sbProcess.GetNumThreads(); for (MIuint i = 0; i < nThreads; i++) { - lldb::SBThread thread = rProcess.GetThreadAtIndex(i); + lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); if (thread.IsValid()) { CMICmnMIValueTuple miTuple; diff --git a/tools/lldb-mi/MICmdCmdVar.cpp b/tools/lldb-mi/MICmdCmdVar.cpp index 4aa4c2ae97cf..e9568beb173c 100644 --- a/tools/lldb-mi/MICmdCmdVar.cpp +++ b/tools/lldb-mi/MICmdCmdVar.cpp @@ -28,8 +28,8 @@ //-- // Third Party Headers: -#include -#include +#include "lldb/API/SBStream.h" +#include "lldb/API/SBThread.h" // In-house headers: #include "MICmdCmdVar.h" @@ -129,16 +129,15 @@ CMICmdCmdVarCreate::Execute(void) // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; - if (!pArgThread->GetExpectedOption(nThreadId)) + if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } - m_nThreadId = nThreadId; // Retrieve the --frame option's number MIuint64 nFrame = UINT64_MAX; - if (!pArgFrame->GetExpectedOption(nFrame)) + if (pArgThread->GetFound() && !pArgFrame->GetExpectedOption(nFrame)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); return MIstatus::failure; @@ -152,27 +151,41 @@ CMICmdCmdVarCreate::Execute(void) nFrame = pOption->GetValue(); } - bool bAutoName = false; - const CMIUtilString strArgName; + m_strVarName = ""; if (pArgName->GetFound()) { const CMIUtilString &rArg = pArgName->GetValue(); - bAutoName = (rArg == "-"); + const bool bAutoName = (rArg == "-"); + if (bAutoName) + { + m_strVarName = CMIUtilString::Format("var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet()); + CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(); + } + else + m_strVarName = rArg; + } + + bool bCurrentFrame = false; + if (pArgFrameAddr->GetFound()) + { + const CMIUtilString &rStrFrameAddr(pArgFrameAddr->GetValue()); + bCurrentFrame = CMIUtilString::Compare(rStrFrameAddr, "*"); + if (!bCurrentFrame && (nFrame == UINT64_MAX)) + { + //FIXME: *addr isn't implemented. Exit with error if --thread isn't specified. + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); + return MIstatus::failure; + } } const CMIUtilString &rStrExpression(pArgExpression->GetValue()); m_strExpression = rStrExpression; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - m_strVarName = ""; - if (bAutoName) - { - m_strVarName = CMIUtilString::Format("var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet()); - CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(); - } - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetThreadByIndexID(nThreadId); - lldb::SBFrame frame = thread.GetFrameAtIndex(nFrame); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); + m_nThreadId = thread.GetIndexID(); + lldb::SBFrame frame = bCurrentFrame ? thread.GetSelectedFrame() : thread.GetFrameAtIndex(nFrame); lldb::SBValue value = frame.FindVariable(rStrExpression.c_str()); if (!value.IsValid()) value = frame.EvaluateExpression(rStrExpression.c_str()); @@ -260,7 +273,8 @@ CMICmdCmdVarCreate::CreateSelf(void) // Throws: None. //-- CMICmdCmdVarUpdate::CMICmdCmdVarUpdate(void) - : m_constStrArgPrintValues("print-values") + : m_eVarInfoFormat(CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues) + , m_constStrArgPrintValues("print-values") , m_constStrArgName("name") , m_bValueChangedArrayType(false) , m_bValueChangedCompositeType(false) @@ -297,7 +311,7 @@ CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate(void) bool CMICmdCmdVarUpdate::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, false))); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, true))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); return (bOk && ParseValidateCmdOptions()); } @@ -314,6 +328,7 @@ CMICmdCmdVarUpdate::ParseArgs(void) bool CMICmdCmdVarUpdate::Execute(void) { + CMICMDBASE_GETOPTION(pArgPrintValues, Number, m_constStrArgPrintValues); CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); const CMIUtilString &rVarObjName(pArgName->GetValue()); @@ -324,6 +339,14 @@ CMICmdCmdVarUpdate::Execute(void) return MIstatus::failure; } + const MIuint nPrintValues = pArgPrintValues->GetValue(); + if (nPrintValues >= CMICmnLLDBDebugSessionInfo::kNumVariableInfoFormats) + { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + m_eVarInfoFormat = static_cast(nPrintValues); + const CMIUtilString &rVarRealName(varObj.GetNameReal()); MIunused(rVarRealName); lldb::SBValue &rValue = const_cast(varObj.GetValue()); @@ -413,9 +436,12 @@ CMICmdCmdVarUpdate::Acknowledge(void) const CMICmnMIValueConst miValueConst(m_strValueName); CMICmnMIValueResult miValueResult("name", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueConst miValueConst2(strValue); - CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); + if (m_eVarInfoFormat != CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues) + { + const CMICmnMIValueConst miValueConst2(strValue); + CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + } const CMICmnMIValueConst miValueConst3(strInScope); CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); miValueTuple.Add(miValueResult3); @@ -519,8 +545,8 @@ CMICmdCmdVarUpdate::ExamineSBValueForChange(const CMICmnLLDBDebugSessionInfoVarO vrwbChanged = false; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); if (thread.GetNumFrames() == 0) { return MIstatus::success; @@ -964,7 +990,10 @@ CMICmdCmdVarListChildren::CMICmdCmdVarListChildren(void) , m_nChildren(0) , m_constStrArgPrintValues("print-values") , m_constStrArgName("name") -{ + , m_constStrArgNoValues("no-values") + , m_constStrArgAllValues("all-values") + , m_constStrArgSimpleValues("simple-values") + { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "var-list-children"; @@ -996,7 +1025,10 @@ CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren(void) bool CMICmdCmdVarListChildren::ParseArgs(void) { - bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, false))); + bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgPrintValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgNoValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgAllValues, false, true))); + bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgSimpleValues, false, true))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgName, true, true))); return (bOk && ParseValidateCmdOptions()); } @@ -1014,6 +1046,24 @@ bool CMICmdCmdVarListChildren::Execute(void) { CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgPrintValue, Number, m_constStrArgPrintValues); + CMICMDBASE_GETOPTION(pArgNoValue, OptionLong, m_constStrArgNoValues); + CMICMDBASE_GETOPTION(pArgAllValue, OptionLong, m_constStrArgAllValues); + CMICMDBASE_GETOPTION(pArgSimpleValue, OptionLong, m_constStrArgSimpleValues); + + MIuint print_value = 0; + if (pArgPrintValue->GetFound()) + { + MIuint tmp = pArgPrintValue->GetValue(); + if (tmp <= 2) + print_value = tmp; + } + else if (pArgNoValue->GetFound()) + print_value = 0; // no value + else if (pArgAllValue->GetFound()) + print_value = 1; // all values + else if (pArgSimpleValue->GetFound()) + print_value = 2; // simple values const CMIUtilString &rVarObjName(pArgName->GetValue()); CMICmnLLDBDebugSessionInfoVarObj varObj; @@ -1041,9 +1091,6 @@ CMICmdCmdVarListChildren::Execute(void) const MIuint nChildren = member.GetNumChildren(); const CMIUtilString strThreadId(CMIUtilString::Format("%u", member.GetThread().GetIndexID())); - // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs - CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName); - // MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}" const CMICmnMIValueConst miValueConst(name); const CMICmnMIValueResult miValueResult("name", miValueConst); @@ -1061,11 +1108,23 @@ CMICmdCmdVarListChildren::Execute(void) const CMICmnMIValueConst miValueConst6(strThreadId); const CMICmnMIValueResult miValueResult6("thread-id", miValueConst6); miValueTuple.Add(miValueResult6); - const CMICmnMIValueConst miValueConst7("0"); - const CMICmnMIValueResult miValueResult7("has_more", miValueConst7); - miValueTuple.Add(miValueResult7); - const CMICmnMIValueResult miValueResult8("child", miValueTuple); - m_vecMiValueResult.push_back(miValueResult8); + // nChildren == 0 is used to check for simple values + if ( (print_value == 2 && nChildren == 0) || (print_value == 1) ) + { + // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs + CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName); + const CMIUtilString strValue( + CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural)); + const CMICmnMIValueConst miValueConst7(strValue); + const CMICmnMIValueResult miValueResult7("value", miValueConst7); + miValueTuple.Add(miValueResult7); + } + const CMICmnMIValueConst miValueConst8("0"); + const CMICmnMIValueResult miValueResult8("has_more", miValueConst8); + miValueTuple.Add(miValueResult8); + const CMICmnMIValueResult miValueResult9("child", miValueTuple); + m_vecMiValueResult.push_back(miValueResult9); + } return MIstatus::success; @@ -1493,7 +1552,7 @@ CMICmdCmdVarShowAttributes::Execute(void) const CMIUtilString &rVarObjName(pArgName->GetValue()); CMICmnLLDBDebugSessionInfoVarObj varObj; - if (CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); return MIstatus::failure; diff --git a/tools/lldb-mi/MICmdCmdVar.h b/tools/lldb-mi/MICmdCmdVar.h index 34ce9e15af6c..add2058c029b 100644 --- a/tools/lldb-mi/MICmdCmdVar.h +++ b/tools/lldb-mi/MICmdCmdVar.h @@ -42,6 +42,7 @@ #include "MICmdBase.h" #include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugSessionInfoVarObj.h" // Declarations: @@ -129,6 +130,7 @@ class CMICmdCmdVarUpdate : public CMICmdBase // Attribute: private: CMIUtilString m_strValueName; + CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e m_eVarInfoFormat; const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command const CMIUtilString m_constStrArgName; bool m_bValueChangedArrayType; // True = yes value changed, false = no change @@ -274,8 +276,11 @@ class CMICmdCmdVarListChildren : public CMICmdBase bool m_bValueValid; // True = yes SBValue object is valid, false = not valid VecMIValueResult_t m_vecMiValueResult; MIuint m_nChildren; - const CMIUtilString m_constStrArgPrintValues; // Not handled by *this command + const CMIUtilString m_constStrArgPrintValues; const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgNoValues; + const CMIUtilString m_constStrArgAllValues; + const CMIUtilString m_constStrArgSimpleValues; }; //++ ============================================================================ diff --git a/tools/lldb-mi/MICmnLLDBBroadcaster.h b/tools/lldb-mi/MICmnLLDBBroadcaster.h index 70d092589412..62ca0542dbf1 100644 --- a/tools/lldb-mi/MICmnLLDBBroadcaster.h +++ b/tools/lldb-mi/MICmnLLDBBroadcaster.h @@ -22,7 +22,7 @@ #pragma once // In-house headers: -#include +#include "lldb/API/SBBroadcaster.h" #include "MICmnBase.h" #include "MIUtilSingletonBase.h" diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp index 3e9ed226182f..7f6d9d53811a 100644 --- a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp +++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp @@ -20,13 +20,13 @@ //-- // Third party headers: -#include +#include "lldb/API/SBThread.h" #ifdef _WIN32 #include // For the ::_access() #else #include // For the ::access() #endif // _WIN32 -#include +#include "lldb/API/SBBreakpointLocation.h" // In-house headers: #include "MICmnLLDBDebugSessionInfo.h" @@ -47,9 +47,7 @@ // Throws: None. //-- CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo(void) - : m_rLldbDebugger(CMICmnLLDBDebugger::Instance().GetTheDebugger()) - , m_rLlldbListener(CMICmnLLDBDebugger::Instance().GetTheListener()) - , m_nBrkPointCntMax(INT32_MAX) + : m_nBrkPointCntMax(INT32_MAX) , m_currentSelectedThread(LLDB_INVALID_THREAD_ID) , m_constStrSharedDataKeyWkDir("Working Directory") , m_constStrSharedDataSolibPath("Solib Path") @@ -226,7 +224,7 @@ CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) bool CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames) { - lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID(vThreadIdx); + lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx); const uint32_t nFrames = thread.GetNumFrames(); if (nFrames == 0) { @@ -255,7 +253,7 @@ CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MI // Function args CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = eVariableType_Arguments; - if (!MIResponseFormVariableInfo(frame, maskVarTypes, miValueList)) + if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList)) return MIstatus::failure; const MIchar *pUnknown = "??"; @@ -299,7 +297,7 @@ CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MI bool CMICmnLLDBDebugSessionInfo::GetThreadFrames2(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames) { - lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID(vThreadIdx); + lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx); const uint32_t nFrames = thread.GetNumFrames(); if (nFrames == 0) { @@ -328,7 +326,7 @@ CMICmnLLDBDebugSessionInfo::GetThreadFrames2(const SMICmdData &vCmdData, const M // Function args CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = eVariableType_Arguments; - if (!MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList)) + if (!MIResponseFormVariableInfo2(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList)) return MIstatus::failure; const MIchar *pUnknown = "??"; @@ -648,6 +646,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2(const SMICmdData &vCmdData // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vMaskVarTypes - (R) Construed according to VariableType_e. +// veVarInfoFormat - (R) The type of variable info that should be shown. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. @@ -655,7 +654,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2(const SMICmdData &vCmdData //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, - CMICmnMIValueList &vwrMiValueList) + const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList) { bool bOk = MIstatus::success; lldb::SBFrame &rFrame = const_cast(vrFrame); @@ -688,6 +687,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2(const lldb::SBFrame &vrF // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vMaskVarTypes - (R) Construed according to VariableType_e. +// veVarInfoFormat - (R) The type of variable info that should be shown. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. @@ -695,7 +695,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2(const lldb::SBFrame &vrF //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, - CMICmnMIValueList &vwrMiValueList) + const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList) { bool bOk = MIstatus::success; lldb::SBFrame &rFrame = const_cast(vrFrame); @@ -711,7 +711,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr for (MIuint i = 0; bOk && (i < nArgs); i++) { lldb::SBValue value = listArg.GetValueAtIndex(i); - bOk = GetVariableInfo(nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth); + bOk = GetVariableInfo(nMaxRecusiveDepth, value, false, veVarInfoFormat, vwrMiValueList, nCurrentRecursiveDepth); } return bOk; @@ -725,6 +725,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vMaskVarTypes - (R) Construed according to VariableType_e. +// veVarInfoFormat - (R) The type of variable info that should be shown. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. @@ -732,7 +733,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFr //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, - CMICmnMIValueList &vwrMiValueList) + const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList) { bool bOk = MIstatus::success; lldb::SBFrame &rFrame = const_cast(vrFrame); @@ -748,7 +749,7 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrF for (MIuint i = 0; bOk && (i < nArgs); i++) { lldb::SBValue value = listArg.GetValueAtIndex(i); - bOk = GetVariableInfo2(nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth); + bOk = GetVariableInfo2(nMaxRecusiveDepth, value, false, veVarInfoFormat, vwrMiValueList, nCurrentRecursiveDepth); } return bOk; @@ -763,15 +764,17 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrF // vrValue - (R) LLDB value object. // vbIsChildValue - (R) True = Value object is a child of a higher Value object, // - False = Value object not a child. +// veVarInfoFormat - (R) The type of variable info that should be shown. // vwrMIValueList - (W) MI value list object. // vnDepth - (RW) The current recursive depth of this function. -// // Return: MIstatus::success - Functional succeeded. +// Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, - CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth) + const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, + MIuint &vrwnDepth) { // *** Update GetVariableInfo2() with any code changes here *** @@ -809,46 +812,78 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb: else { // Basic types - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); - const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); + switch (veVarInfoFormat) + { + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + break; + } + default: + break; + } return vwrMiValueList.Add(miValueTuple); } } else if (bIsPointerType && utilValue.IsChildCharType()) { - // Append string text to the parent value information - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); + switch (veVarInfoFormat) + { + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + // Append string text to the parent value information + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); - const CMIUtilString &rText(utilValue.GetChildValueCString()); - if (rText.empty()) - { - const CMICmnMIValueConst miValueConst(utilValue.GetValue()); - const CMICmnMIValueResult miValueResult("value", miValueConst); - miValueTuple.Add(miValueResult); - } - else - { - if (utilValue.IsValueUnknown()) - { - const CMICmnMIValueConst miValueConst(rText); - const CMICmnMIValueResult miValueResult("value", miValueConst); - miValueTuple.Add(miValueResult); - } - else - { - // Note code that has const in will not show the text suffix to the string pointer - // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this - // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); - const CMICmnMIValueResult miValueResult("value", miValueConst); - miValueTuple.Add(miValueResult); + const CMIUtilString &rText(utilValue.GetChildValueCString()); + if (rText.empty()) + { + const CMICmnMIValueConst miValueConst(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + if (utilValue.IsValueUnknown()) + { + const CMICmnMIValueConst miValueConst(rText); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + // Note code that has const in will not show the text suffix to the string pointer + // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this + // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + } + break; } + default: + break; } return vwrMiValueList.Add(miValueTuple); } @@ -865,30 +900,62 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb: else { // Basic types - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); - const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); + switch (veVarInfoFormat) + { + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + break; + } + default: + break; + } return vwrMiValueList.Add(miValueTuple); } } else { - // Build parent child composite types - CMICmnMIValueList miValueList(true); - for (MIuint i = 0; bOk && (i < nChildren); i++) + switch (veVarInfoFormat) { - lldb::SBValue member = rValue.GetChildAtIndex(i); - bOk = GetVariableInfo(vnMaxDepth, member, true, miValueList, ++vrwnDepth); + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + // Build parent child composite types + CMICmnMIValueList miValueList(true); + for (MIuint i = 0; bOk && (i < nChildren); i++) + { + lldb::SBValue member = rValue.GetChildAtIndex(i); + bOk = GetVariableInfo(vnMaxDepth, member, true, veVarInfoFormat, miValueList, ++vrwnDepth); + } + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + break; + } + default: + break; } - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); - const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } @@ -902,6 +969,7 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb: // vrValue - (R) LLDB value object. // vbIsChildValue - (R) True = Value object is a child of a higher Value object, // - False = Value object not a child. +// veVarInfoFormat - (R) The type of variable info that should be shown. // vwrMIValueList - (W) MI value list object. // vnDepth - (RW) The current recursive depth of this function. // // Return: MIstatus::success - Functional succeeded. @@ -910,7 +978,8 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb: //-- bool CMICmnLLDBDebugSessionInfo::GetVariableInfo2(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, - CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth) + const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, + MIuint &vrwnDepth) { // *** Update GetVariableInfo() with any code changes here *** @@ -937,64 +1006,112 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo2(const MIuint vnMaxDepth, const lldb else { // Basic types - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); - const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); + switch (veVarInfoFormat) + { + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + break; + } + default: + break; + } return vwrMiValueList.Add(miValueTuple); } } else if (utilValue.IsChildCharType()) { - // Append string text to the parent value information - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); + switch (veVarInfoFormat) + { + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + // Append string text to the parent value information + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); - const CMIUtilString &rText(utilValue.GetChildValueCString()); - if (rText.empty()) - { - const CMICmnMIValueConst miValueConst(utilValue.GetValue()); - const CMICmnMIValueResult miValueResult("value", miValueConst); - miValueTuple.Add(miValueResult); - } - else - { - if (utilValue.IsValueUnknown()) - { - const CMICmnMIValueConst miValueConst(rText); - const CMICmnMIValueResult miValueResult("value", miValueConst); - miValueTuple.Add(miValueResult); - } - else - { - // Note code that has const in will not show the text suffix to the string pointer - // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this - // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); - const CMICmnMIValueResult miValueResult("value", miValueConst); - miValueTuple.Add(miValueResult); + const CMIUtilString &rText(utilValue.GetChildValueCString()); + if (rText.empty()) + { + const CMICmnMIValueConst miValueConst(utilValue.GetValue()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + if (utilValue.IsValueUnknown()) + { + const CMICmnMIValueConst miValueConst(rText); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + else + { + // Note code that has const in will not show the text suffix to the string pointer + // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this + // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); + const CMICmnMIValueResult miValueResult("value", miValueConst); + miValueTuple.Add(miValueResult); + } + } + break; } + default: + break; } return vwrMiValueList.Add(miValueTuple); } else { - // Build parent child composite types - CMICmnMIValueList miValueList(true); - for (MIuint i = 0; bOk && (i < nChildren); i++) + switch (veVarInfoFormat) { - lldb::SBValue member = rValue.GetChildAtIndex(i); - bOk = GetVariableInfo(vnMaxDepth, member, true, miValueList, ++vrwnDepth); + case eVariableInfoFormat_NoValues: + { + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + return vwrMiValueList.Add(miValueResult); + } + case eVariableInfoFormat_AllValues: + case eVariableInfoFormat_SimpleValues: + { + // Build parent child composite types + CMICmnMIValueList miValueList(true); + for (MIuint i = 0; bOk && (i < nChildren); i++) + { + lldb::SBValue member = rValue.GetChildAtIndex(i); + bOk = GetVariableInfo(vnMaxDepth, member, true, veVarInfoFormat, miValueList, ++vrwnDepth); + } + const CMICmnMIValueConst miValueConst(utilValue.GetName()); + const CMICmnMIValueResult miValueResult("name", miValueConst); + miValueTuple.Add(miValueResult); + const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + break; + } + default: + break; } - const CMICmnMIValueConst miValueConst(utilValue.GetName()); - const CMICmnMIValueResult miValueResult("name", miValueConst); - miValueTuple.Add(miValueResult); - const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } @@ -1329,7 +1446,7 @@ CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkP const MIchar *pFn = pUnkwn; const MIchar *pFilePath = pUnkwn; size_t nLine = 0; - const size_t nAddr = brkPtAddr.GetLoadAddress(m_lldbTarget); + const size_t nAddr = brkPtAddr.GetLoadAddress(GetTarget()); lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); if (rCmplUnit.IsValid()) @@ -1356,3 +1473,55 @@ CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkP return MIstatus::success; } + +//++ ------------------------------------------------------------------------------------ +// Details: Get current debugger. +// Type: Method. +// Args: None. +// Return: lldb::SBDebugger - current debugger. +// Throws: None. +//-- +lldb::SBDebugger & +CMICmnLLDBDebugSessionInfo::GetDebugger() const +{ + return CMICmnLLDBDebugger::Instance().GetTheDebugger(); +} + +//++ ------------------------------------------------------------------------------------ +// Details: Get current listener. +// Type: Method. +// Args: None. +// Return: lldb::SBListener - current listener. +// Throws: None. +//-- +lldb::SBListener & +CMICmnLLDBDebugSessionInfo::GetListener() const +{ + return CMICmnLLDBDebugger::Instance().GetTheListener(); +} + +//++ ------------------------------------------------------------------------------------ +// Details: Get current target. +// Type: Method. +// Args: None. +// Return: lldb::SBTarget - current target. +// Throws: None. +//-- +lldb::SBTarget +CMICmnLLDBDebugSessionInfo::GetTarget() const +{ + return GetDebugger().GetSelectedTarget(); +} + +//++ ------------------------------------------------------------------------------------ +// Details: Get current process. +// Type: Method. +// Args: None. +// Return: lldb::SBProcess - current process. +// Throws: None. +//-- +lldb::SBProcess +CMICmnLLDBDebugSessionInfo::GetProcess() const +{ + return GetTarget().GetProcess(); +} diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h index e2463f1c89ca..2e592f1f43c6 100644 --- a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h +++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h @@ -24,10 +24,10 @@ // Third party headers: #include #include -#include -#include -#include -#include +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBListener.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBTarget.h" // In-house headers: #include "MICmnBase.h" @@ -35,6 +35,7 @@ #include "MICmnLLDBDebugSessionInfoVarObj.h" #include "MICmnMIValueTuple.h" #include "MIUtilMapIdToVariant.h" +#include "MIUtilThreadBaseStd.h" // Declarations: class CMICmnLLDBDebugger; @@ -116,6 +117,17 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton VecActiveThreadId_t; @@ -147,23 +159,27 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton -#include +#include "lldb/API/SBValue.h" // In-house headers: #include "MIUtilString.h" diff --git a/tools/lldb-mi/MICmnLLDBDebugger.cpp b/tools/lldb-mi/MICmnLLDBDebugger.cpp index 273b805156f4..37ddda4db0ce 100644 --- a/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ b/tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -20,10 +20,10 @@ //-- // Third party headers: -#include -#include -#include -#include +#include "lldb/API/SBTarget.h" +#include "lldb/API/SBThread.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBCommandInterpreter.h" // In-house headers: #include "MICmnLLDBDebugger.h" @@ -148,7 +148,8 @@ CMICmnLLDBDebugger::Shutdown(void) // Explicitly delete the remote target in case MI needs to exit prematurely otherwise // LLDB debugger may hang in its Destroy() fn waiting on events - m_lldbDebugger.DeleteTarget(CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget); + lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget(); + m_lldbDebugger.DeleteTarget(sbTarget); // Debug: May need this but does seem to work without it so commented out the fudge 19/06/2014 // It appears we need to wait as hang does not occur when hitting a debug breakpoint here @@ -663,7 +664,13 @@ CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) bool bHandledEvent = false; bool bExitAppEvent = false; - const bool bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent, bExitAppEvent); + + bool bOk = false; + { + // Lock Mutex before handling events so that we don't disturb a running cmd + CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); + bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent, bExitAppEvent); + } if (!bHandledEvent) { const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), event.GetBroadcasterClass())); diff --git a/tools/lldb-mi/MICmnLLDBDebugger.h b/tools/lldb-mi/MICmnLLDBDebugger.h index 6075fd85e535..403d71d0e32d 100644 --- a/tools/lldb-mi/MICmnLLDBDebugger.h +++ b/tools/lldb-mi/MICmnLLDBDebugger.h @@ -24,9 +24,9 @@ // Third party headers #include #include -#include -#include -#include +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBListener.h" +#include "lldb/API/SBEvent.h" // In-house headers: #include "MICmnBase.h" diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp index b375611ec6ec..50049e643ec7 100644 --- a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp +++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp @@ -20,13 +20,13 @@ //-- // Third party headers: -#include -#include -#include -#include -#include -#include -#include +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBThread.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" #ifdef _WIN32 #include // For the ::_access() #else @@ -722,9 +722,9 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBE return MIstatus::success; bool bOk = MIstatus::success; - lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger; - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBTarget target = rProcess.GetTarget(); + lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger(); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBTarget target = sbProcess.GetTarget(); if (rDebugger.GetSelectedTarget() == target) { if (!UpdateSelectedThread()) @@ -768,8 +768,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(bool &vwrbShouldB const MIchar *pEventType = ""; bool bOk = MIstatus::success; - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason(); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const lldb::StopReason eStoppedReason = sbProcess.GetSelectedThread().GetStopReason(); switch (eStoppedReason) { case lldb::eStopReasonInvalid: @@ -807,6 +807,9 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(bool &vwrbShouldB case lldb::eStopReasonThreadExiting: pEventType = "eStopReasonThreadExiting"; break; + case lldb::eStopReasonInstrumentation: + pEventType = "eStopReasonInstrumentation"; + break; } // ToDo: Remove when finished coding application @@ -828,8 +831,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk { bool bOk = MIstatus::success; - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const MIuint64 nStopReason = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); switch (nStopReason) { case 2: // Terminal interrupt signal. SIGINT @@ -865,7 +868,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk const CMICmnMIValueConst miValueConst3("Segmentation fault"); const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); bOk = bOk && miOutOfBandRecord.Add(miValueResult3); - const CMIUtilString strThreadId(CMIUtilString::Format("%d", rProcess.GetSelectedThread().GetIndexID())); + const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID())); const CMICmnMIValueConst miValueConst4(strThreadId); const CMICmnMIValueResult miValueResult4("thread-id", miValueConst4); bOk = bOk && miOutOfBandRecord.Add(miValueResult4); @@ -878,12 +881,12 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk } break; case 19: - if (rProcess.IsValid()) - rProcess.Continue(); + if (sbProcess.IsValid()) + sbProcess.Continue(); break; case 5: // Trace/breakpoint trap. SIGTRAP { - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); const MIuint nFrames = thread.GetNumFrames(); if (nFrames > 0) { @@ -896,9 +899,9 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk if (CMIUtilString::Compare(threadCloneFn, fnName)) { - if (rProcess.IsValid()) + if (sbProcess.IsValid()) { - rProcess.Continue(); + sbProcess.Continue(); vwrbShouldBrk = true; break; } @@ -939,8 +942,8 @@ bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple) { CMIUtilString strThreadFrame; - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); const MIuint nFrame = thread.GetNumFrames(); if (nFrame == 0) { @@ -994,9 +997,9 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void) return MIstatus::failure; } - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); - lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex((MIuint)brkPtId); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const MIuint64 brkPtId = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); + lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex((MIuint)brkPtId); return MiStoppedAtBreakPoint(brkPtId, brkPt); } @@ -1015,8 +1018,8 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c { bool bOk = MIstatus::success; - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); const MIuint nFrame = thread.GetNumFrames(); if (nFrame == 0) { @@ -1078,7 +1081,7 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c { CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; - bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList); + bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues, miValueList); CMICmnMIValueTuple miValueTuple; bOk = bOk && rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple); @@ -1118,8 +1121,8 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void) { bool bOk = true; - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - lldb::SBThread thread = rProcess.GetSelectedThread(); + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); const MIuint nFrame = thread.GetNumFrames(); if (nFrame == 0) { @@ -1154,7 +1157,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void) // Function args CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; - if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList)) + if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues, miValueList)) return MIstatus::failure; CMICmnMIValueTuple miValueTuple; if (!rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple)) @@ -1197,7 +1200,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void) bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void) { - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); if (!process.IsValid()) return MIstatus::success; @@ -1339,7 +1342,7 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void) char c; size_t nBytes = 0; CMIUtilString text; - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); while (process.GetSTDOUT(&c, 1) > 0) { CMIUtilString str; @@ -1374,7 +1377,7 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void) char c; size_t nBytes = 0; CMIUtilString text; - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess(); + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); while (process.GetSTDERR(&c, 1) > 0) { CMIUtilString str; @@ -1448,22 +1451,22 @@ CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void) { - lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess; - if (!rProcess.IsValid()) + lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + if (!sbProcess.IsValid()) return MIstatus::success; - lldb::SBTarget &rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget; - if (!rTarget.IsValid()) + lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget(); + if (!sbTarget.IsValid()) return MIstatus::success; bool bOk = MIstatus::success; // Check for created threads - const MIuint nThread = rProcess.GetNumThreads(); + const MIuint nThread = sbProcess.GetNumThreads(); for (MIuint i = 0; i < nThread; i++) { // GetThreadAtIndex() uses a base 0 index // GetThreadByIndexID() uses a base 1 index - lldb::SBThread thread = rProcess.GetThreadAtIndex(i); + lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); if (!thread.IsValid()) continue; @@ -1500,7 +1503,7 @@ CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void) } } - lldb::SBThread currentThread = rProcess.GetSelectedThread(); + lldb::SBThread currentThread = sbProcess.GetSelectedThread(); if (currentThread.IsValid()) { const MIuint threadId = currentThread.GetIndexID(); @@ -1523,7 +1526,7 @@ CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void) while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end()) { const MIuint nThreadId = *it; - lldb::SBThread thread = rProcess.GetThreadAtIndex(nThreadId); + lldb::SBThread thread = sbProcess.GetThreadAtIndex(nThreadId); if (!thread.IsValid()) { // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\"" diff --git a/tools/lldb-mi/MICmnLLDBProxySBValue.cpp b/tools/lldb-mi/MICmnLLDBProxySBValue.cpp index a4f36b400fa7..6a07f207840e 100644 --- a/tools/lldb-mi/MICmnLLDBProxySBValue.cpp +++ b/tools/lldb-mi/MICmnLLDBProxySBValue.cpp @@ -22,7 +22,7 @@ #include // Third Party Headers: -#include +#include "lldb/API/SBError.h" // In-house headers: #include "MICmnLLDBProxySBValue.h" @@ -129,14 +129,14 @@ CMICmnLLDBProxySBValue::GetCString(const lldb::SBValue &vrValue, CMIUtilString & return MIstatus::failure; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess &rProcess = rSessionInfo.m_lldbProcess; + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); MIuint nBufferSize = 64; bool bNeedResize = false; MIchar *pBuffer = static_cast(::malloc(nBufferSize)); do { lldb::SBError error; - const size_t nReadSize = rProcess.ReadCStringFromMemory((lldb::addr_t)nNum, pBuffer, nBufferSize, error); + const size_t nReadSize = sbProcess.ReadCStringFromMemory((lldb::addr_t)nNum, pBuffer, nBufferSize, error); if (nReadSize == (nBufferSize - 1)) { bNeedResize = true; diff --git a/tools/lldb-mi/MICmnLLDBProxySBValue.h b/tools/lldb-mi/MICmnLLDBProxySBValue.h index e21eb95a2dd9..39befe9566f3 100644 --- a/tools/lldb-mi/MICmnLLDBProxySBValue.h +++ b/tools/lldb-mi/MICmnLLDBProxySBValue.h @@ -22,7 +22,7 @@ #pragma once // Third Party Headers: -#include +#include "lldb/API/SBValue.h" // In-house headers: #include "MIDataTypes.h" diff --git a/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp b/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp index 847bba2c8d0a..66a4efd5a96e 100644 --- a/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ b/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -219,7 +219,7 @@ CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(const lldb::SBValue &vrValueObj const MIuint nBytes(128); const MIchar *pBufferMemory = new MIchar[nBytes]; lldb::SBError error; - const MIuint64 nReadBytes = rSessionInfo.m_lldbProcess.ReadMemory(addr, (void *)pBufferMemory, nBytes, error); + const MIuint64 nReadBytes = rSessionInfo.GetProcess().ReadMemory(addr, (void *)pBufferMemory, nBytes, error); MIunused(nReadBytes); text = CMIUtilString::Format("\\\"%s\\\"", pBufferMemory); delete[] pBufferMemory; diff --git a/tools/lldb-mi/MICmnLLDBUtilSBValue.h b/tools/lldb-mi/MICmnLLDBUtilSBValue.h index 1aa3022960b7..a3f2c9c0ffc9 100644 --- a/tools/lldb-mi/MICmnLLDBUtilSBValue.h +++ b/tools/lldb-mi/MICmnLLDBUtilSBValue.h @@ -22,7 +22,7 @@ #pragma once // Third Party Headers: -#include +#include "lldb/API/SBValue.h" // In-house headers: #include "MIDataTypes.h" diff --git a/tools/lldb-mi/MICmnLog.cpp b/tools/lldb-mi/MICmnLog.cpp index a18fd2d4e502..dc7a93d29776 100644 --- a/tools/lldb-mi/MICmnLog.cpp +++ b/tools/lldb-mi/MICmnLog.cpp @@ -73,7 +73,6 @@ CMICmnLog::Initialize(void) // Mediums set inside because explicitly initing in MIDriverMain.cpp causes compile errors with CAtlFile CMICmnLogMediumFile &rFileLog(CMICmnLogMediumFile::Instance()); bool bOk = RegisterMedium(rFileLog); - bOk = bOk && SetEnabled(true); if (bOk) { // Set the Log trace file's header diff --git a/tools/lldb-mi/MICmnResources.cpp b/tools/lldb-mi/MICmnResources.cpp index 676e9e743986..bc1fa3025cd6 100644 --- a/tools/lldb-mi/MICmnResources.cpp +++ b/tools/lldb-mi/MICmnResources.cpp @@ -82,7 +82,7 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] {IDE_MI_APP_ARG_EXECUTEABLE, "--executable\n\tUse the MI Driver in MI mode for the debugging the specified\n\texecutable. Any LLDB " "command line options are ignored even\n\tif the MI Driver falls through to the LLDB driver. " "(Depends\n\ton the build configuration see MICmnConfig.h)\n\tNormally specified from the command line."}, - {IDE_MI_APP_ARG_NO_APP_LOG, "--noLog\n\tUse this argument to tell the MI Driver not to update it's log\n\tfile '%s'."}, + {IDE_MI_APP_ARG_APP_LOG, "--log\n\tUse this argument to tell the MI Driver to update it's log\n\tfile '%s'."}, {IDE_MI_APP_ARG_EXAMPLE, "Example MI command:\n\t3-info-gdb-mi-command gdb-set\n\t3^done,command={exists=\"true\"}"}, {IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file path to the executable i.e. '\"C:\\My Dev\\foo.exe\"'."}, {IDS_STDIN_ERR_INVALID_PROMPT, "Stdin. Invalid prompt description '%s'"}, @@ -254,6 +254,7 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] {IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, "Command '%s'. LLDB unable to read entire memory block of %u bytes at address 0x%08x"}, {IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to read memory block of %u bytes at address 0x%08x: %s "}, {IDS_CMD_ERR_INVALID_PROCESS, "Command '%s'. Invalid process during debug session"}, + {IDS_CMD_ERR_INVALID_PRINT_VALUES, "Command '%s'. Unknown value for PRINT_VALUES: must be: 0 or \"--no-values\", 1 or \"all-values\", 2 or \"simple-values\""}, {IDS_CMD_ERR_INVALID_FORMAT_TYPE, "Command '%s'. Invalid var format type '%s'"}, {IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, "Command '%s'. Breakpoint information for breakpoint ID %d not found"}, {IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to write memory block of %u bytes at address 0x%08x: %s "}, diff --git a/tools/lldb-mi/MICmnResources.h b/tools/lldb-mi/MICmnResources.h index cd9208cfb7a4..b561473fbb79 100644 --- a/tools/lldb-mi/MICmnResources.h +++ b/tools/lldb-mi/MICmnResources.h @@ -89,7 +89,7 @@ enum IDE_MI_APP_ARG_VERSION_LONG, IDE_MI_APP_ARG_INTERPRETER, IDE_MI_APP_ARG_EXECUTEABLE, - IDE_MI_APP_ARG_NO_APP_LOG, + IDE_MI_APP_ARG_APP_LOG, IDE_MI_APP_ARG_EXAMPLE, IDE_MI_APP_ARG_EXECUTABLE, @@ -270,6 +270,7 @@ enum IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, IDS_CMD_ERR_INVALID_PROCESS, + IDS_CMD_ERR_INVALID_PRINT_VALUES, IDS_CMD_ERR_INVALID_FORMAT_TYPE, IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES, diff --git a/tools/lldb-mi/MIDriver.cpp b/tools/lldb-mi/MIDriver.cpp index accde1c7cde7..5628e344952b 100644 --- a/tools/lldb-mi/MIDriver.cpp +++ b/tools/lldb-mi/MIDriver.cpp @@ -22,7 +22,7 @@ // Third party headers: #include // va_list, va_start, var_end #include -#include +#include "lldb/API/SBError.h" // In-house headers: #include "Driver.h" @@ -41,6 +41,7 @@ #include "MICmdArgValFile.h" #include "MICmdArgValString.h" #include "MICmnConfig.h" +#include "MICmnLLDBDebugSessionInfo.h" // Instantiations: #if _DEBUG @@ -687,7 +688,13 @@ CMIDriver::ReadStdinLineQueue(void) } // Process the command - const bool bOk = InterpretCommand(lineText); + bool bOk = false; + { + // Lock Mutex before processing commands so that we don't disturb an event + // that is being processed. + CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); + bOk = InterpretCommand(lineText); + } // Draw prompt if desired if (bOk && m_rStdin.GetEnablePrompt()) diff --git a/tools/lldb-mi/MIDriverBase.cpp b/tools/lldb-mi/MIDriverBase.cpp index fd9fae821196..fd1a0eca5536 100644 --- a/tools/lldb-mi/MIDriverBase.cpp +++ b/tools/lldb-mi/MIDriverBase.cpp @@ -20,8 +20,8 @@ //-- // Third party headers: -#include -#include +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBBroadcaster.h" // In-house headers: #include "MIDriverBase.h" diff --git a/tools/lldb-mi/MIDriverBase.h b/tools/lldb-mi/MIDriverBase.h index 7516efd13b75..25ac23887282 100644 --- a/tools/lldb-mi/MIDriverBase.h +++ b/tools/lldb-mi/MIDriverBase.h @@ -22,8 +22,8 @@ #pragma once // Third party headers: -#include -#include +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBBroadcaster.h" // In-house headers: #include "MIUtilString.h" diff --git a/tools/lldb-mi/MIDriverMain.cpp b/tools/lldb-mi/MIDriverMain.cpp index b14fb815b6e6..5557799d3680 100644 --- a/tools/lldb-mi/MIDriverMain.cpp +++ b/tools/lldb-mi/MIDriverMain.cpp @@ -49,7 +49,7 @@ // Third party headers: #include -#include +#include "lldb/API/SBHostOS.h" // In house headers: #include "MICmnConfig.h" @@ -81,6 +81,9 @@ void sigwinch_handler(int vSigno) { +#ifdef _WIN32 // Restore handler as it is not persistent on Windows + signal(SIGWINCH, sigwinch_handler); +#endif MIunused(vSigno); struct winsize window_size; @@ -111,6 +114,9 @@ sigwinch_handler(int vSigno) void sigint_handler(int vSigno) { +#ifdef _WIN32 // Restore handler as it is not persistent on Windows + signal(SIGINT, sigint_handler); +#endif static bool g_interrupt_sent = false; CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); @@ -147,6 +153,9 @@ sigint_handler(int vSigno) void sigtstp_handler(int vSigno) { +#ifdef _WIN32 // Restore handler as it is not persistent on Windows + signal(SIGTSTP, sigtstp_handler); +#endif CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); if (pDebugger != nullptr) @@ -175,6 +184,9 @@ sigtstp_handler(int vSigno) void sigcont_handler(int vSigno) { +#ifdef _WIN32 // Restore handler as it is not persistent on Windows + signal(SIGCONT, sigcont_handler); +#endif CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); if (pDebugger != nullptr) diff --git a/tools/lldb-mi/MIDriverMgr.cpp b/tools/lldb-mi/MIDriverMgr.cpp index 79b44ca947ad..ca900ca6e885 100644 --- a/tools/lldb-mi/MIDriverMgr.cpp +++ b/tools/lldb-mi/MIDriverMgr.cpp @@ -20,7 +20,7 @@ //-- // Third Party Headers: -#include +#include "lldb/API/SBError.h" // In-house headers: #include "MIDriverMgr.h" @@ -125,8 +125,6 @@ CMIDriverMgr::Shutdown(void) if (vbAppExitOk) { - // The MI Driver's log updating may have been switched off switch back on to say all is ok. - CMICmnLog::Instance().SetEnabled(true); #if _DEBUG CMICmnStreamStdout::Instance().Write(MIRSRC(IDE_MI_APP_EXIT_OK)); // Both stdout and Log #else @@ -144,8 +142,6 @@ CMIDriverMgr::Shutdown(void) } else { - // The MI Driver's log updating may have been switched off switch back on to say there has been problem. - rAppLog.SetEnabled(true); const CMIUtilString msg( CMIUtilString::Format(MIRSRC(IDE_MI_APP_EXIT_WITH_PROBLEM_NO_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str())); CMICmnStreamStdout::Instance().Write(msg); @@ -495,7 +491,7 @@ CMIDriverMgr::DriverGetTheDebugger(void) // --interpreter // --version // --versionLong -// --noLog +// --log // --executable // The above arguments are not handled by any driver object except for --executable. // The options --interpreter and --executable in code act very similar. The @@ -552,7 +548,7 @@ CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting) bool bHaveArgInterpret = false; bool bHaveArgVersion = false; bool bHaveArgVersionLong = false; - bool bHaveArgNoLog = false; + bool bHaveArgLog = false; bool bHaveArgHelp = false; // Hardcode the use of the MI driver @@ -582,9 +578,9 @@ CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting) { bHaveArgVersionLong = true; } - if (0 == strArg.compare("--noLog")) + if (0 == strArg.compare("--log")) { - bHaveArgNoLog = true; + bHaveArgLog = true; } if ((0 == strArg.compare("--help")) || (0 == strArg.compare("-h"))) { @@ -593,9 +589,9 @@ CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting) } } - if (bHaveArgNoLog) + if (bHaveArgLog) { - CMICmnLog::Instance().SetEnabled(false); + CMICmnLog::Instance().SetEnabled(true); } // Todo: Remove this output when MI is finished. It is temporary to persuade Ecllipse plugin to work. @@ -687,7 +683,7 @@ CMIDriverMgr::GetHelpOnCmdLineArgOptions(void) const MIRSRC(IDE_MI_APP_ARG_VERSION_LONG), MIRSRC(IDE_MI_APP_ARG_INTERPRETER), MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE), - CMIUtilString::Format(MIRSRC(IDE_MI_APP_ARG_NO_APP_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str()), + CMIUtilString::Format(MIRSRC(IDE_MI_APP_ARG_APP_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str()), MIRSRC(IDE_MI_APP_ARG_EXECUTABLE), MIRSRC(IDS_CMD_QUIT_HELP), MIRSRC(IDE_MI_APP_ARG_EXAMPLE)}; diff --git a/tools/lldb-mi/MIDriverMgr.h b/tools/lldb-mi/MIDriverMgr.h index d9449277b063..9e1e121405cb 100644 --- a/tools/lldb-mi/MIDriverMgr.h +++ b/tools/lldb-mi/MIDriverMgr.h @@ -23,7 +23,7 @@ // Third party headers: #include -#include +#include "lldb/API/SBDebugger.h" // In-house headers: #include "MICmnBase.h" diff --git a/tools/lldb-mi/MIReadMe.txt b/tools/lldb-mi/MIReadMe.txt index fbd3b2d364f6..47d28e395ede 100644 --- a/tools/lldb-mi/MIReadMe.txt +++ b/tools/lldb-mi/MIReadMe.txt @@ -1,5 +1,5 @@ ======================================================================== - The MI Driver - LLDB Machine Interface V2 (MI) Project Overview + The MI Driver - LLDB Machine Interface V2 (MI) Project Overview 24/07/2014 ======================================================================== From 5e95aa85bb660d45e9905ef1d7180b2678280660 Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Fri, 3 Jul 2015 16:57:06 +0000 Subject: [PATCH 2/2] Import LLDB as of upstream SVN 241361 (git 612c075f) --- include/lldb/API/LLDB.h | 1 + include/lldb/API/SBAddress.h | 2 +- include/lldb/API/SBAttachInfo.h | 149 + include/lldb/API/SBBlock.h | 2 +- include/lldb/API/SBBreakpoint.h | 2 +- include/lldb/API/SBBreakpointLocation.h | 6 +- include/lldb/API/SBBroadcaster.h | 2 +- include/lldb/API/SBCommandInterpreter.h | 33 +- include/lldb/API/SBCommandReturnObject.h | 2 +- include/lldb/API/SBCommunication.h | 5 +- include/lldb/API/SBCompileUnit.h | 2 +- include/lldb/API/SBData.h | 2 +- include/lldb/API/SBDebugger.h | 4 +- include/lldb/API/SBDeclaration.h | 2 +- include/lldb/API/SBDefines.h | 3 + include/lldb/API/SBError.h | 2 +- include/lldb/API/SBEvent.h | 3 +- include/lldb/API/SBExecutionContext.h | 2 +- include/lldb/API/SBExpressionOptions.h | 8 +- include/lldb/API/SBFileSpec.h | 2 +- include/lldb/API/SBFileSpecList.h | 2 +- include/lldb/API/SBFrame.h | 21 +- include/lldb/API/SBFunction.h | 2 +- include/lldb/API/SBHostOS.h | 2 +- include/lldb/API/SBInstruction.h | 2 +- include/lldb/API/SBInstructionList.h | 2 +- include/lldb/API/SBLanguageRuntime.h | 29 + include/lldb/API/SBLaunchInfo.h | 13 +- include/lldb/API/SBLineEntry.h | 2 +- include/lldb/API/SBListener.h | 2 +- include/lldb/API/SBModule.h | 21 +- include/lldb/API/SBModuleSpec.h | 2 +- include/lldb/API/SBPlatform.h | 6 +- include/lldb/API/SBProcess.h | 24 +- include/lldb/API/SBQueue.h | 2 +- include/lldb/API/SBQueueItem.h | 2 +- include/lldb/API/SBSection.h | 2 +- include/lldb/API/SBSourceManager.h | 2 +- include/lldb/API/SBStream.h | 2 +- include/lldb/API/SBStringList.h | 2 +- include/lldb/API/SBSymbol.h | 2 +- include/lldb/API/SBSymbolContext.h | 2 +- include/lldb/API/SBSymbolContextList.h | 2 +- include/lldb/API/SBTarget.h | 165 +- include/lldb/API/SBThread.h | 2 +- include/lldb/API/SBThreadCollection.h | 2 +- include/lldb/API/SBThreadPlan.h | 2 +- include/lldb/API/SBType.h | 2 +- include/lldb/API/SBTypeCategory.h | 2 +- include/lldb/API/SBTypeEnumMember.h | 2 +- include/lldb/API/SBTypeFilter.h | 2 +- include/lldb/API/SBTypeFormat.h | 2 +- include/lldb/API/SBTypeNameSpecifier.h | 2 +- include/lldb/API/SBTypeSummary.h | 2 +- include/lldb/API/SBTypeSynthetic.h | 2 +- include/lldb/API/SBUnixSignals.h | 2 +- include/lldb/API/SBValue.h | 14 +- include/lldb/API/SBValueList.h | 2 +- include/lldb/API/SBVariablesOptions.h | 98 + include/lldb/API/SBWatchpoint.h | 2 +- include/lldb/API/SystemInitializerFull.h | 40 + include/lldb/Breakpoint/Breakpoint.h | 58 +- include/lldb/Breakpoint/BreakpointLocation.h | 5 +- include/lldb/Breakpoint/BreakpointOptions.h | 3 + .../Breakpoint/BreakpointResolverFileLine.h | 4 +- .../Breakpoint/BreakpointResolverFileRegex.h | 4 +- include/lldb/Breakpoint/BreakpointSite.h | 2 +- include/lldb/Breakpoint/Watchpoint.h | 18 +- include/lldb/Core/Address.h | 2 + include/lldb/Core/ArchSpec.h | 141 +- include/lldb/Core/ClangForward.h | 3 + include/lldb/Core/Communication.h | 30 +- include/lldb/Core/Connection.h | 23 + include/lldb/Core/ConstString.h | 2 +- include/lldb/Core/CxaDemangle.h | 21 + include/lldb/Core/DataEncoder.h | 4 +- include/lldb/Core/DataExtractor.h | 14 +- include/lldb/Core/Debugger.h | 30 +- include/lldb/Core/Disassembler.h | 11 +- include/lldb/Core/FastDemangle.h | 24 + include/lldb/Core/FormatEntity.h | 3 + include/lldb/Core/IOHandler.h | 150 +- include/lldb/Core/Log.h | 140 +- .../{lldb-private-log.h => Core/Logging.h} | 9 +- include/lldb/Core/Mangled.h | 17 +- include/lldb/Core/Module.h | 12 +- include/lldb/Core/ModuleList.h | 4 + include/lldb/Core/ModuleSpec.h | 33 +- include/lldb/Core/PluginManager.h | 6 +- include/lldb/Core/RangeMap.h | 27 +- include/lldb/Core/StreamAsynchronousIO.h | 8 +- include/lldb/Core/StreamFile.h | 4 + include/lldb/Core/StringList.h | 4 + include/lldb/Core/StructuredData.h | 408 +- include/lldb/Core/ThreadSafeDenseSet.h | 65 + include/lldb/Core/ValueObject.h | 65 +- include/lldb/Core/ValueObjectChild.h | 3 + include/lldb/Core/ValueObjectDynamicValue.h | 12 + .../lldb/Core/ValueObjectSyntheticFilter.h | 15 + .../DataFormatters/CXXFormatterFunctions.h | 35 +- include/lldb/DataFormatters/FormatManager.h | 4 + include/lldb/DataFormatters/TypeFormat.h | 27 + include/lldb/DataFormatters/TypeSummary.h | 33 +- include/lldb/DataFormatters/TypeSynthetic.h | 30 +- include/lldb/DataFormatters/TypeValidator.h | 27 + .../lldb/DataFormatters/ValueObjectPrinter.h | 5 + .../lldb/DataFormatters/VectorType.h | 0 include/lldb/Expression/ClangASTSource.h | 127 +- .../lldb/Expression/ClangExpressionDeclMap.h | 21 +- .../lldb/Expression/ClangExpressionParser.h | 1 - include/lldb/Expression/ClangFunction.h | 3 +- .../lldb/Expression/ClangModulesDeclVendor.h | 73 +- .../Expression/ClangPersistentVariables.h | 16 + include/lldb/Expression/ClangUserExpression.h | 13 +- include/lldb/Expression/IRForTarget.h | 3 + include/lldb/Expression/IRMemoryMap.h | 12 +- include/lldb/Expression/IRToDWARF.h | 2 +- include/lldb/Host/Editline.h | 18 +- include/lldb/Host/File.h | 2 +- include/lldb/Host/FileSpec.h | 131 +- include/lldb/Host/FileSystem.h | 31 +- include/lldb/Host/Host.h | 45 +- include/lldb/Host/HostInfo.h | 5 + include/lldb/Host/HostInfoBase.h | 4 +- include/lldb/Host/LockFile.h | 27 + include/lldb/Host/LockFileBase.h | 73 + include/lldb/Host/PipeBase.h | 2 + include/lldb/Host/Socket.h | 7 +- include/lldb/Host/Time.h | 26 + include/lldb/Host/XML.h | 234 + .../lldb/Host/common/NativeBreakpointList.h | 3 + .../lldb/Host/common/NativeProcessProtocol.h | 20 +- .../lldb/Host/common/NativeRegisterContext.h | 19 +- include/lldb/Host/common/SoftwareBreakpoint.h | 2 + .../posix/ConnectionFileDescriptorPosix.h | 18 +- include/lldb/Host/posix/Fcntl.h | 25 + include/lldb/Host/posix/HostProcessPosix.h | 10 +- include/lldb/Host/posix/HostThreadPosix.h | 4 +- include/lldb/Host/posix/LockFilePosix.h | 42 + include/lldb/Host/posix/PipePosix.h | 17 +- .../lldb/Host/posix/ProcessLauncherPosix.h | 2 +- .../lldb/Initialization/SystemInitializer.h | 26 + .../Initialization/SystemInitializerCommon.h | 38 + .../Initialization/SystemLifetimeManager.h | 42 + include/lldb/Interpreter/Args.h | 17 +- include/lldb/Interpreter/CommandInterpreter.h | 13 + include/lldb/Interpreter/CommandObject.h | 90 +- include/lldb/Interpreter/OptionValue.h | 16 +- include/lldb/Interpreter/OptionValueArch.h | 2 +- include/lldb/Interpreter/OptionValueArray.h | 2 +- include/lldb/Interpreter/OptionValueBoolean.h | 2 +- include/lldb/Interpreter/OptionValueChar.h | 2 +- .../lldb/Interpreter/OptionValueDictionary.h | 2 +- .../lldb/Interpreter/OptionValueEnumeration.h | 2 +- .../lldb/Interpreter/OptionValueFileSpec.h | 13 +- .../Interpreter/OptionValueFileSpecList.h | 2 +- include/lldb/Interpreter/OptionValueFormat.h | 2 +- .../Interpreter/OptionValueFormatEntity.h | 2 +- .../lldb/Interpreter/OptionValueLanguage.h | 107 + .../Interpreter/OptionValuePathMappings.h | 2 +- .../lldb/Interpreter/OptionValueProperties.h | 2 +- include/lldb/Interpreter/OptionValueRegex.h | 2 +- include/lldb/Interpreter/OptionValueSInt64.h | 2 +- include/lldb/Interpreter/OptionValueString.h | 2 +- include/lldb/Interpreter/OptionValueUInt64.h | 2 +- include/lldb/Interpreter/OptionValueUUID.h | 2 +- include/lldb/Interpreter/OptionValues.h | 1 + include/lldb/Interpreter/PythonDataObjects.h | 107 +- include/lldb/Interpreter/ScriptInterpreter.h | 335 +- .../Interpreter/ScriptInterpreterPython.h | 286 +- include/lldb/Symbol/ClangASTContext.h | 2 +- include/lldb/Symbol/ClangASTType.h | 4 +- .../Symbol/ClangExternalASTSourceCallbacks.h | 76 +- include/lldb/Symbol/CompileUnit.h | 25 +- include/lldb/Symbol/DWARFCallFrameInfo.h | 10 + include/lldb/Symbol/FuncUnwinders.h | 4 +- include/lldb/Symbol/ObjectFile.h | 7 + include/lldb/Symbol/Symbol.h | 88 +- include/lldb/Symbol/SymbolContext.h | 29 +- include/lldb/Symbol/SymbolFile.h | 1 + include/lldb/Symbol/SymbolVendor.h | 7 + include/lldb/Symbol/Symtab.h | 8 + include/lldb/Symbol/Type.h | 12 +- include/lldb/Symbol/UnwindPlan.h | 248 +- include/lldb/Symbol/Variable.h | 2 +- include/lldb/Target/CPPLanguageRuntime.h | 3 + include/lldb/Target/FileAction.h | 17 +- include/lldb/Target/LanguageRuntime.h | 30 +- include/lldb/Target/Memory.h | 17 +- include/lldb/Target/ObjCLanguageRuntime.h | 62 +- include/lldb/Target/Platform.h | 152 +- include/lldb/Target/Process.h | 262 +- include/lldb/Target/ProcessInfo.h | 2 +- include/lldb/Target/ProcessLaunchInfo.h | 36 +- include/lldb/Target/SectionLoadHistory.h | 2 +- include/lldb/Target/StopInfo.h | 8 +- include/lldb/Target/Target.h | 227 +- include/lldb/Target/Thread.h | 50 +- .../Target/ThreadPlanCallUserExpression.h | 13 +- include/lldb/Target/ThreadPlanPython.h | 5 +- include/lldb/Utility/ConvertEnum.h | 22 + include/lldb/Utility/JSON.h | 276 + include/lldb/Utility/LLDBAssert.h | 30 + include/lldb/Utility/NameMatches.h | 19 + include/lldb/Utility/PseudoTerminal.h | 4 +- include/lldb/Utility/SharingPtr.h | 11 +- include/lldb/lldb-defines.h | 2 +- include/lldb/lldb-enumerations.h | 332 +- include/lldb/lldb-forward.h | 33 +- include/lldb/lldb-private-interfaces.h | 1 + include/lldb/lldb-private-types.h | 11 + include/lldb/lldb-private.h | 53 - source/API/SBAddress.cpp | 2 + source/API/SBAttachInfo.cpp | 242 + source/API/SBCommandInterpreter.cpp | 242 +- source/API/SBDebugger.cpp | 63 +- source/API/SBEvent.cpp | 2 - source/API/SBExpressionOptions.cpp | 11 + source/API/SBFileSpec.cpp | 14 +- source/API/SBFrame.cpp | 115 +- source/API/SBInstruction.cpp | 4 +- source/API/SBInstructionList.cpp | 2 +- source/API/SBLanguageRuntime.cpp | 26 + source/API/SBLaunchInfo.cpp | 26 +- source/API/SBListener.cpp | 2 - source/API/SBModule.cpp | 66 +- source/API/SBPlatform.cpp | 14 +- source/API/SBProcess.cpp | 52 +- source/API/SBQueue.cpp | 2 - source/API/SBQueueItem.cpp | 1 - source/API/SBSourceManager.cpp | 2 - source/API/SBSymbol.cpp | 9 +- source/API/SBTarget.cpp | 562 +- source/API/SBThread.cpp | 12 +- source/API/SBThreadPlan.cpp | 2 - source/API/SBTypeCategory.cpp | 2 - source/API/SBTypeFilter.cpp | 2 - source/API/SBTypeFormat.cpp | 2 - source/API/SBTypeNameSpecifier.cpp | 2 - source/API/SBTypeSummary.cpp | 2 - source/API/SBTypeSynthetic.cpp | 2 - source/API/SBValue.cpp | 57 +- source/API/SBVariablesOptions.cpp | 254 + source/API/SystemInitializerFull.cpp | 392 ++ source/Breakpoint/Breakpoint.cpp | 46 +- source/Breakpoint/BreakpointLocation.cpp | 8 +- .../BreakpointLocationCollection.cpp | 10 +- source/Breakpoint/BreakpointResolver.cpp | 1 - .../Breakpoint/BreakpointResolverAddress.cpp | 2 +- .../Breakpoint/BreakpointResolverFileLine.cpp | 14 +- .../BreakpointResolverFileRegex.cpp | 14 +- source/Breakpoint/BreakpointSite.cpp | 3 + source/Commands/CommandCompletions.cpp | 3 +- source/Commands/CommandObjectApropos.cpp | 3 +- source/Commands/CommandObjectArgs.cpp | 4 +- source/Commands/CommandObjectBreakpoint.cpp | 108 +- .../CommandObjectBreakpointCommand.cpp | 2 - source/Commands/CommandObjectBugreport.cpp | 145 + source/Commands/CommandObjectBugreport.h | 36 + source/Commands/CommandObjectCommands.cpp | 264 +- source/Commands/CommandObjectDisassemble.cpp | 2 - source/Commands/CommandObjectExpression.cpp | 6 +- source/Commands/CommandObjectFrame.cpp | 50 +- source/Commands/CommandObjectGUI.cpp | 2 - source/Commands/CommandObjectHelp.cpp | 2 - source/Commands/CommandObjectLanguage.cpp | 44 + source/Commands/CommandObjectLanguage.h | 41 + source/Commands/CommandObjectLog.cpp | 6 +- source/Commands/CommandObjectMemory.cpp | 44 +- source/Commands/CommandObjectMultiword.cpp | 38 +- source/Commands/CommandObjectPlatform.cpp | 25 +- source/Commands/CommandObjectPlugin.cpp | 2 - source/Commands/CommandObjectProcess.cpp | 155 +- source/Commands/CommandObjectQuit.cpp | 3 +- source/Commands/CommandObjectRegister.cpp | 21 +- source/Commands/CommandObjectSettings.cpp | 5 +- source/Commands/CommandObjectSource.cpp | 12 +- source/Commands/CommandObjectSyntax.cpp | 2 - source/Commands/CommandObjectTarget.cpp | 197 +- source/Commands/CommandObjectThread.cpp | 110 +- source/Commands/CommandObjectType.cpp | 4 +- source/Commands/CommandObjectVersion.cpp | 2 - source/Commands/CommandObjectWatchpoint.cpp | 21 +- .../CommandObjectWatchpointCommand.cpp | 2 - source/Core/Address.cpp | 26 +- source/Core/AddressResolver.cpp | 1 - source/Core/AddressResolverFileLine.cpp | 1 - source/Core/AddressResolverName.cpp | 5 +- source/Core/ArchSpec.cpp | 150 +- source/Core/Broadcaster.cpp | 1 - source/Core/Communication.cpp | 43 +- source/Core/ConnectionMachPort.cpp | 5 +- source/Core/ConnectionSharedMemory.cpp | 1 - source/Core/CxaDemangle.cpp | 5011 ++++++++++++++++ source/Core/DataBufferHeap.cpp | 2 +- source/Core/DataBufferMemoryMap.cpp | 14 +- source/Core/DataEncoder.cpp | 14 +- source/Core/DataExtractor.cpp | 2 +- source/Core/Debugger.cpp | 305 +- source/Core/Disassembler.cpp | 110 +- source/Core/DynamicLoader.cpp | 18 + source/Core/Error.cpp | 4 - source/Core/FastDemangle.cpp | 13 +- source/Core/FileLineResolver.cpp | 1 - source/Core/FormatEntity.cpp | 66 +- source/Core/IOHandler.cpp | 272 +- source/Core/Language.cpp | 20 +- source/Core/Listener.cpp | 1 - source/Core/Log.cpp | 288 +- source/{lldb-log.cpp => Core/Logging.cpp} | 8 +- source/Core/Mangled.cpp | 5065 +---------------- source/Core/Module.cpp | 77 +- source/Core/ModuleList.cpp | 58 +- source/Core/PluginManager.cpp | 17 +- source/Core/Scalar.cpp | 6 +- source/Core/SearchFilter.cpp | 2 +- source/Core/Section.cpp | 1 + source/Core/SourceManager.cpp | 3 +- source/Core/StreamAsynchronousIO.cpp | 25 +- source/Core/StreamFile.cpp | 7 + source/Core/StringList.cpp | 6 + source/Core/StructuredData.cpp | 67 +- source/Core/UUID.cpp | 3 + source/Core/UserSettingsController.cpp | 3 +- source/Core/ValueObject.cpp | 242 +- source/Core/ValueObjectChild.cpp | 8 + source/Core/ValueObjectConstResult.cpp | 2 +- source/Core/ValueObjectSyntheticFilter.cpp | 14 +- source/Core/ValueObjectVariable.cpp | 2 +- source/DataFormatters/CF.cpp | 2 - .../DataFormatters/CXXFormatterFunctions.cpp | 7 +- source/DataFormatters/Cocoa.cpp | 2 - source/DataFormatters/CoreMedia.cpp | 85 + source/DataFormatters/DataVisualization.cpp | 2 - source/DataFormatters/FormatCache.cpp | 2 - source/DataFormatters/FormatManager.cpp | 73 +- source/DataFormatters/LibCxx.cpp | 4 +- .../DataFormatters/LibCxxInitializerList.cpp | 2 - source/DataFormatters/LibCxxList.cpp | 2 - source/DataFormatters/LibCxxMap.cpp | 2 - source/DataFormatters/LibCxxUnorderedMap.cpp | 2 - source/DataFormatters/LibCxxVector.cpp | 2 - source/DataFormatters/LibStdcpp.cpp | 171 - source/DataFormatters/NSArray.cpp | 2 - source/DataFormatters/NSDictionary.cpp | 2 - source/DataFormatters/NSIndexPath.cpp | 219 +- source/DataFormatters/NSSet.cpp | 2 - source/DataFormatters/StringPrinter.cpp | 32 +- source/DataFormatters/TypeCategory.cpp | 2 - source/DataFormatters/TypeCategoryMap.cpp | 2 - source/DataFormatters/TypeFormat.cpp | 3 +- source/DataFormatters/TypeSummary.cpp | 2 - source/DataFormatters/TypeSynthetic.cpp | 6 +- source/DataFormatters/ValueObjectPrinter.cpp | 28 +- source/DataFormatters/VectorType.cpp | 276 + source/Expression/ClangASTSource.cpp | 140 +- source/Expression/ClangExpressionDeclMap.cpp | 290 +- source/Expression/ClangExpressionParser.cpp | 48 +- source/Expression/ClangModulesDeclVendor.cpp | 398 +- source/Expression/ClangUserExpression.cpp | 97 +- source/Expression/DWARFExpression.cpp | 26 +- source/Expression/ExpressionSourceCode.cpp | 98 +- source/Expression/IRExecutionUnit.cpp | 25 +- source/Expression/IRForTarget.cpp | 94 +- source/Expression/Materializer.cpp | 3 +- source/Host/common/Editline.cpp | 125 +- source/Host/common/File.cpp | 162 +- source/Host/common/FileSpec.cpp | 414 +- source/Host/common/FileSystem.cpp | 103 + source/Host/common/Host.cpp | 180 +- source/Host/common/HostInfoBase.cpp | 92 +- source/Host/common/LockFileBase.cpp | 124 + source/Host/common/NativeBreakpointList.cpp | 22 + source/Host/common/NativeProcessProtocol.cpp | 6 + source/Host/common/NativeRegisterContext.cpp | 58 +- source/Host/common/Socket.cpp | 89 +- source/Host/common/SocketAddress.cpp | 11 +- source/Host/common/SoftwareBreakpoint.cpp | 56 +- source/Host/common/Symbols.cpp | 316 +- source/Host/common/Terminal.cpp | 6 +- source/Host/common/XML.cpp | 693 +++ source/Host/freebsd/Host.cpp | 36 +- source/Host/freebsd/HostThreadFreeBSD.cpp | 2 + source/Host/freebsd/ThisThread.cpp | 9 + .../posix/ConnectionFileDescriptorPosix.cpp | 62 +- source/Host/posix/FileSystem.cpp | 183 +- source/Host/posix/HostInfoPosix.cpp | 32 +- source/Host/posix/HostProcessPosix.cpp | 17 +- source/Host/posix/LockFilePosix.cpp | 77 + source/Host/posix/PipePosix.cpp | 24 +- source/Initialization/SystemInitializer.cpp | 20 + .../SystemInitializerCommon.cpp | 185 + .../Initialization/SystemLifetimeManager.cpp | 61 + source/Interpreter/Args.cpp | 395 +- source/Interpreter/CommandInterpreter.cpp | 471 +- source/Interpreter/CommandObject.cpp | 70 +- .../Interpreter/CommandObjectRegexCommand.cpp | 2 - source/Interpreter/CommandObjectScript.cpp | 2 - source/Interpreter/OptionGroupBoolean.cpp | 2 +- source/Interpreter/OptionGroupFile.cpp | 4 +- source/Interpreter/OptionGroupFormat.cpp | 8 +- source/Interpreter/OptionGroupOutputFile.cpp | 4 +- source/Interpreter/OptionGroupPlatform.cpp | 2 - source/Interpreter/OptionGroupString.cpp | 2 +- source/Interpreter/OptionGroupUInt64.cpp | 2 +- source/Interpreter/OptionGroupUUID.cpp | 2 +- .../OptionGroupValueObjectDisplay.cpp | 2 - source/Interpreter/OptionGroupVariable.cpp | 2 - source/Interpreter/OptionGroupWatchpoint.cpp | 4 +- source/Interpreter/OptionValue.cpp | 43 +- source/Interpreter/OptionValueArch.cpp | 19 +- source/Interpreter/OptionValueArray.cpp | 12 +- source/Interpreter/OptionValueBoolean.cpp | 13 +- source/Interpreter/OptionValueChar.cpp | 8 +- source/Interpreter/OptionValueDictionary.cpp | 22 +- source/Interpreter/OptionValueEnumeration.cpp | 15 +- source/Interpreter/OptionValueFileSpec.cpp | 46 +- .../Interpreter/OptionValueFileSpecLIst.cpp | 6 +- source/Interpreter/OptionValueFormat.cpp | 8 +- .../Interpreter/OptionValueFormatEntity.cpp | 30 +- source/Interpreter/OptionValueLanguage.cpp | 73 + .../Interpreter/OptionValuePathMappings.cpp | 6 +- source/Interpreter/OptionValueProperties.cpp | 6 +- source/Interpreter/OptionValueRegex.cpp | 6 +- source/Interpreter/OptionValueSInt64.cpp | 11 +- source/Interpreter/OptionValueString.cpp | 32 +- source/Interpreter/OptionValueUInt64.cpp | 11 +- source/Interpreter/OptionValueUUID.cpp | 10 +- source/Interpreter/Options.cpp | 4 +- source/Interpreter/Property.cpp | 27 +- source/Interpreter/PythonDataObjects.cpp | 143 +- source/Interpreter/ScriptInterpreter.cpp | 57 - source/Interpreter/ScriptInterpreterNone.cpp | 2 - .../Interpreter/ScriptInterpreterPython.cpp | 862 ++- .../Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 27 +- .../ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp | 24 +- .../ABI/MacOSX-i386/ABIMacOSX_i386.cpp | 12 +- source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp | 916 +++ source/Plugins/ABI/SysV-arm/ABISysV_arm.h | 121 + .../Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp | 1081 ++++ source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h | 125 + .../ABI/SysV-hexagon/ABISysV_hexagon.cpp | 13 +- source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp | 815 +++ source/Plugins/ABI/SysV-i386/ABISysV_i386.h | 138 + source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp | 590 ++ source/Plugins/ABI/SysV-mips/ABISysV_mips.h | 123 + .../ABI/SysV-mips64/ABISysV_mips64.cpp | 570 ++ .../Plugins/ABI/SysV-mips64/ABISysV_mips64.h | 133 + source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp | 21 +- .../Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp | 21 +- .../ABI/SysV-x86_64/ABISysV_x86_64.cpp | 24 +- .../Disassembler/llvm/DisassemblerLLVMC.cpp | 105 +- .../Disassembler/llvm/DisassemblerLLVMC.h | 2 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 4 +- .../Hexagon-DYLD/HexagonDYLDRendezvous.cpp | 1 + .../POSIX-DYLD/DYLDRendezvous.cpp | 60 +- .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.h | 23 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 102 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 6 +- .../Instruction/ARM/EmulateInstructionARM.cpp | 455 +- .../Instruction/ARM/EmulationStateARM.cpp | 2 +- .../ARM64/EmulateInstructionARM64.cpp | 387 +- .../ARM64/EmulateInstructionARM64.h | 43 +- .../MIPS/EmulateInstructionMIPS.cpp | 2918 ++++++++++ .../Instruction/MIPS/EmulateInstructionMIPS.h | 313 + .../MIPS64/EmulateInstructionMIPS64.cpp | 2920 ++++++++++ .../MIPS64/EmulateInstructionMIPS64.h | 313 + .../AddressSanitizerRuntime.cpp | 55 +- source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 9 +- .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 51 + .../ItaniumABI/ItaniumABILanguageRuntime.h | 6 + .../RenderScriptRuntime.cpp | 1191 ++++ .../RenderScriptRuntime/RenderScriptRuntime.h | 232 + .../BSD-Archive/ObjectContainerBSDArchive.cpp | 7 +- source/Plugins/ObjectFile/ELF/ELFHeader.cpp | 5 +- .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 455 +- source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 94 +- .../Plugins/ObjectFile/JIT/ObjectFileJIT.cpp | 1 - .../Python/OperatingSystemPython.cpp | 192 +- .../Python/OperatingSystemPython.h | 23 +- .../Platform/FreeBSD/PlatformFreeBSD.cpp | 533 +- .../Platform/FreeBSD/PlatformFreeBSD.h | 255 +- .../Plugins/Platform/POSIX/PlatformPOSIX.cpp | 91 +- source/Plugins/Platform/POSIX/PlatformPOSIX.h | 84 +- .../gdb-server/PlatformRemoteGDBServer.cpp | 319 +- .../gdb-server/PlatformRemoteGDBServer.h | 232 +- .../Plugins/Process/FreeBSD/FreeBSDThread.cpp | 1 + .../{POSIX => FreeBSD}/POSIXStopInfo.cpp | 0 .../{POSIX => FreeBSD}/POSIXStopInfo.h | 0 .../{POSIX => FreeBSD}/POSIXThread.cpp | 70 +- .../Process/{POSIX => FreeBSD}/POSIXThread.h | 33 +- .../Process/FreeBSD/ProcessFreeBSD.cpp | 19 +- .../Process/FreeBSD/ProcessMonitor.cpp | 68 +- .../Plugins/Process/FreeBSD/ProcessMonitor.h | 35 +- .../{POSIX => FreeBSD}/ProcessPOSIX.cpp | 175 +- .../Process/{POSIX => FreeBSD}/ProcessPOSIX.h | 68 +- ...RegisterContextPOSIXProcessMonitor_arm.cpp | 322 ++ .../RegisterContextPOSIXProcessMonitor_arm.h | 95 + ...gisterContextPOSIXProcessMonitor_arm64.cpp | 8 +- ...RegisterContextPOSIXProcessMonitor_arm64.h | 0 ...isterContextPOSIXProcessMonitor_mips64.cpp | 5 +- ...egisterContextPOSIXProcessMonitor_mips64.h | 0 ...sterContextPOSIXProcessMonitor_powerpc.cpp | 3 +- ...gisterContextPOSIXProcessMonitor_powerpc.h | 0 ...RegisterContextPOSIXProcessMonitor_x86.cpp | 9 +- .../RegisterContextPOSIXProcessMonitor_x86.h | 0 source/Plugins/Process/POSIX/CrashReason.cpp | 42 +- .../Plugins/Process/POSIX/ProcessPOSIXLog.cpp | 19 +- .../Plugins/Process/POSIX/ProcessPOSIXLog.h | 6 + .../Process/Utility/DynamicRegisterInfo.cpp | 677 ++- .../Process/Utility/DynamicRegisterInfo.h | 14 +- .../Process/Utility/FreeBSDSignals.cpp | 70 +- .../Process/Utility/InferiorCallPOSIX.cpp | 9 +- .../Process/Utility/InferiorCallPOSIX.h | 5 - .../Plugins/Process/Utility/LinuxSignals.cpp | 103 +- source/Plugins/Process/Utility/LinuxSignals.h | 8 +- .../Process/Utility/MipsLinuxSignals.cpp | 95 + .../Process/Utility/MipsLinuxSignals.h | 37 + .../Utility/RegisterContextFreeBSD_arm.cpp | 88 + .../Utility/RegisterContextFreeBSD_arm.h | 75 + .../Utility/RegisterContextFreeBSD_arm64.cpp | 86 + .../Utility/RegisterContextFreeBSD_arm64.h | 78 + .../Utility/RegisterContextFreeBSD_i386.cpp | 7 + .../Utility/RegisterContextFreeBSD_x86_64.cpp | 25 +- .../Process/Utility/RegisterContextLLDB.cpp | 198 +- .../Utility/RegisterContextLinux_arm.cpp | 87 + .../Utility/RegisterContextLinux_arm.h | 76 + .../Utility/RegisterContextLinux_i386.cpp | 3 +- .../Utility/RegisterContextLinux_mips.cpp | 102 + .../Utility/RegisterContextLinux_mips.h | 32 + .../Utility/RegisterContextLinux_mips64.cpp | 143 + .../Utility/RegisterContextLinux_mips64.h | 40 + .../Utility/RegisterContextLinux_x86_64.cpp | 13 +- .../Utility/RegisterContextPOSIX_arm.cpp | 287 + .../Utility/RegisterContextPOSIX_arm.h | 121 + .../Utility/RegisterContextPOSIX_arm64.cpp | 3 + .../Utility/RegisterContextPOSIX_arm64.h | 159 +- .../Utility/RegisterContextPOSIX_mips64.h | 54 +- .../Utility/RegisterContextPOSIX_powerpc.cpp | 3 +- .../Process/Utility/RegisterContext_mips64.h | 232 + .../Process/Utility/RegisterInfos_arm.h | 303 + .../Process/Utility/RegisterInfos_arm64.h | 16 +- .../Process/Utility/RegisterInfos_i386.h | 14 +- .../Process/Utility/RegisterInfos_mips.h | 122 + .../Process/Utility/RegisterInfos_mips64.h | 90 +- .../Process/Utility/RegisterInfos_x86_64.h | 17 +- .../Process/Utility/StopInfoMachException.cpp | 7 +- .../Plugins/Process/Utility/ThreadMemory.cpp | 2 +- source/Plugins/Process/Utility/UnwindLLDB.cpp | 1 + .../Process/Utility/lldb-arm-register-enums.h | 153 + .../Utility/lldb-arm64-register-enums.h | 172 + .../Utility/lldb-mips64-register-enums.h | 199 + .../Process/elf-core/ProcessElfCore.cpp | 18 +- .../Plugins/Process/elf-core/ProcessElfCore.h | 39 +- .../elf-core/RegisterContextPOSIXCore_arm.cpp | 94 + .../elf-core/RegisterContextPOSIXCore_arm.h | 60 + .../RegisterContextPOSIXCore_arm64.cpp | 94 + .../elf-core/RegisterContextPOSIXCore_arm64.h | 60 + .../Process/elf-core/ThreadElfCore.cpp | 24 + .../gdb-remote/GDBRemoteCommunication.cpp | 655 ++- .../gdb-remote/GDBRemoteCommunication.h | 126 +- .../GDBRemoteCommunicationClient.cpp | 1101 +++- .../gdb-remote/GDBRemoteCommunicationClient.h | 239 +- .../GDBRemoteCommunicationServer.cpp | 4462 +-------------- .../gdb-remote/GDBRemoteCommunicationServer.h | 525 +- .../GDBRemoteCommunicationServerCommon.cpp | 1341 +++++ .../GDBRemoteCommunicationServerCommon.h | 216 + .../GDBRemoteCommunicationServerLLGS.cpp | 2787 +++++++++ .../GDBRemoteCommunicationServerLLGS.h | 307 + .../GDBRemoteCommunicationServerPlatform.cpp | 376 ++ .../GDBRemoteCommunicationServerPlatform.h | 102 + .../gdb-remote/GDBRemoteRegisterContext.cpp | 22 +- .../gdb-remote/GDBRemoteRegisterContext.h | 77 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 2296 ++++++-- .../Process/gdb-remote/ProcessGDBRemote.h | 243 +- .../gdb-remote/ProcessGDBRemoteLog.cpp | 19 + .../Process/gdb-remote/ProcessGDBRemoteLog.h | 21 +- .../Process/gdb-remote/ThreadGDBRemote.cpp | 60 +- .../Process/gdb-remote/ThreadGDBRemote.h | 92 +- .../SymbolFile/DWARF/DWARFCompileUnit.cpp | 56 + .../SymbolFile/DWARF/DWARFCompileUnit.h | 8 + .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 22 +- .../SymbolFile/DWARF/DWARFDebugLine.cpp | 69 +- .../SymbolFile/DWARF/DWARFDeclContext.h | 8 + .../SymbolFile/DWARF/DWARFFormValue.cpp | 2 +- source/Plugins/SymbolFile/DWARF/NameToDIE.cpp | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 388 +- .../SymbolFile/DWARF/SymbolFileDWARF.h | 51 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 244 +- .../DWARF/SymbolFileDWARFDebugMap.h | 101 +- .../SymbolFile/Symtab/SymbolFileSymtab.cpp | 8 +- .../SymbolFile/Symtab/SymbolFileSymtab.h | 3 + .../UnwindAssemblyInstEmulation.cpp | 228 +- .../UnwindAssemblyInstEmulation.h | 11 +- .../UnwindAssembly/x86/UnwindAssembly-x86.cpp | 143 +- source/Symbol/Block.cpp | 2 - source/Symbol/ClangASTContext.cpp | 54 +- source/Symbol/ClangASTImporter.cpp | 12 +- source/Symbol/ClangASTType.cpp | 97 +- .../ClangExternalASTSourceCallbacks.cpp | 13 +- source/Symbol/CompactUnwindInfo.cpp | 77 +- source/Symbol/CompileUnit.cpp | 25 +- source/Symbol/DWARFCallFrameInfo.cpp | 602 +- source/Symbol/FuncUnwinders.cpp | 59 +- source/Symbol/LineTable.cpp | 3 +- source/Symbol/ObjectFile.cpp | 3 +- source/Symbol/Symbol.cpp | 62 +- source/Symbol/SymbolContext.cpp | 47 +- source/Symbol/SymbolVendor.cpp | 31 + source/Symbol/Symtab.cpp | 62 +- source/Symbol/Type.cpp | 23 +- source/Symbol/UnwindPlan.cpp | 141 +- source/Symbol/Variable.cpp | 13 +- source/Target/ABI.cpp | 1 + source/Target/ExecutionContext.cpp | 35 +- source/Target/FileAction.cpp | 23 +- source/Target/LanguageRuntime.cpp | 84 +- source/Target/Memory.cpp | 139 +- source/Target/ObjCLanguageRuntime.cpp | 47 +- source/Target/Platform.cpp | 498 +- source/Target/Process.cpp | 570 +- source/Target/ProcessLaunchInfo.cpp | 119 +- source/Target/StackFrame.cpp | 8 +- source/Target/StackFrameList.cpp | 17 +- source/Target/StopInfo.cpp | 48 +- source/Target/Target.cpp | 583 +- source/Target/TargetList.cpp | 43 +- source/Target/Thread.cpp | 37 +- source/Target/ThreadList.cpp | 6 +- source/Target/ThreadPlan.cpp | 4 +- source/Target/ThreadPlanCallFunction.cpp | 4 +- .../Target/ThreadPlanCallUserExpression.cpp | 4 +- source/Target/ThreadPlanPython.cpp | 3 - source/Target/ThreadPlanRunToAddress.cpp | 1 - source/Target/ThreadPlanStepInRange.cpp | 3 +- source/Target/ThreadPlanStepInstruction.cpp | 1 - source/Target/ThreadPlanStepOut.cpp | 2 +- .../Target/ThreadPlanStepOverBreakpoint.cpp | 1 - source/Target/ThreadPlanStepOverRange.cpp | 6 +- source/Target/ThreadPlanStepRange.cpp | 9 +- source/Target/ThreadPlanStepThrough.cpp | 1 - source/Target/ThreadPlanStepUntil.cpp | 1 - source/Target/ThreadPlanTracer.cpp | 8 +- source/Utility/ConvertEnum.cpp | 110 + source/Utility/JSON.cpp | 217 + source/Utility/LLDBAssert.cpp | 36 + source/Utility/ModuleCache.cpp | 186 + source/Utility/ModuleCache.h | 78 + source/Utility/NameMatches.cpp | 50 + source/Utility/PseudoTerminal.cpp | 12 +- source/Utility/StringExtractor.cpp | 4 +- source/Utility/StringExtractorGDBRemote.cpp | 13 + source/Utility/StringExtractorGDBRemote.h | 4 + source/Utility/UriParser.cpp | 1 + source/lldb.cpp | 402 +- tools/argdumper/argdumper.cpp | 38 + tools/argdumper/exports | 0 tools/compact-unwind/compact-unwind-dumper.c | 2 +- tools/driver/Driver.cpp | 43 +- tools/driver/Platform.h | 15 +- tools/lldb-mi/Driver.cpp | 1276 ----- tools/lldb-mi/Driver.h | 144 - tools/lldb-mi/MICmdArgContext.cpp | 42 +- tools/lldb-mi/MICmdArgContext.h | 14 - tools/lldb-mi/MICmdArgSet.cpp | 35 +- tools/lldb-mi/MICmdArgSet.h | 12 - tools/lldb-mi/MICmdArgValBase.cpp | 12 - tools/lldb-mi/MICmdArgValBase.h | 14 +- tools/lldb-mi/MICmdArgValConsume.cpp | 24 +- tools/lldb-mi/MICmdArgValConsume.h | 12 - tools/lldb-mi/MICmdArgValFile.cpp | 29 +- tools/lldb-mi/MICmdArgValFile.h | 12 - tools/lldb-mi/MICmdArgValListBase.cpp | 12 - tools/lldb-mi/MICmdArgValListBase.h | 12 - tools/lldb-mi/MICmdArgValListOfN.cpp | 14 +- tools/lldb-mi/MICmdArgValListOfN.h | 22 +- tools/lldb-mi/MICmdArgValNumber.cpp | 41 +- tools/lldb-mi/MICmdArgValNumber.h | 29 +- tools/lldb-mi/MICmdArgValOptionLong.cpp | 16 +- tools/lldb-mi/MICmdArgValOptionLong.h | 12 - tools/lldb-mi/MICmdArgValOptionShort.cpp | 12 - tools/lldb-mi/MICmdArgValOptionShort.h | 12 - tools/lldb-mi/MICmdArgValPrintValues.cpp | 129 + tools/lldb-mi/MICmdArgValPrintValues.h | 53 + tools/lldb-mi/MICmdArgValString.cpp | 238 +- tools/lldb-mi/MICmdArgValString.h | 14 +- tools/lldb-mi/MICmdArgValThreadGrp.cpp | 14 +- tools/lldb-mi/MICmdArgValThreadGrp.h | 12 - tools/lldb-mi/MICmdBase.cpp | 12 - tools/lldb-mi/MICmdBase.h | 12 - tools/lldb-mi/MICmdCmd.cpp | 10 +- tools/lldb-mi/MICmdCmd.h | 10 - tools/lldb-mi/MICmdCmdBreak.cpp | 49 +- tools/lldb-mi/MICmdCmdBreak.h | 10 - tools/lldb-mi/MICmdCmdData.cpp | 392 +- tools/lldb-mi/MICmdCmdData.h | 58 +- tools/lldb-mi/MICmdCmdEnviro.cpp | 10 - tools/lldb-mi/MICmdCmdEnviro.h | 10 - tools/lldb-mi/MICmdCmdExec.cpp | 245 +- tools/lldb-mi/MICmdCmdExec.h | 68 +- tools/lldb-mi/MICmdCmdFile.cpp | 44 +- tools/lldb-mi/MICmdCmdFile.h | 15 +- tools/lldb-mi/MICmdCmdGdbInfo.cpp | 15 +- tools/lldb-mi/MICmdCmdGdbInfo.h | 10 - tools/lldb-mi/MICmdCmdGdbSet.cpp | 180 +- tools/lldb-mi/MICmdCmdGdbSet.h | 17 +- tools/lldb-mi/MICmdCmdGdbShow.cpp | 340 ++ tools/lldb-mi/MICmdCmdGdbShow.h | 86 + tools/lldb-mi/MICmdCmdGdbThread.cpp | 10 - tools/lldb-mi/MICmdCmdGdbThread.h | 10 - tools/lldb-mi/MICmdCmdMiscellanous.cpp | 27 +- tools/lldb-mi/MICmdCmdMiscellanous.h | 10 - tools/lldb-mi/MICmdCmdStack.cpp | 501 +- tools/lldb-mi/MICmdCmdStack.h | 113 +- tools/lldb-mi/MICmdCmdSupportInfo.cpp | 10 - tools/lldb-mi/MICmdCmdSupportInfo.h | 10 - tools/lldb-mi/MICmdCmdSupportList.cpp | 10 - tools/lldb-mi/MICmdCmdSupportList.h | 10 - tools/lldb-mi/MICmdCmdSymbol.cpp | 173 + tools/lldb-mi/MICmdCmdSymbol.h | 57 + tools/lldb-mi/MICmdCmdTarget.cpp | 275 +- tools/lldb-mi/MICmdCmdTarget.h | 69 +- tools/lldb-mi/MICmdCmdThread.cpp | 20 +- tools/lldb-mi/MICmdCmdThread.h | 10 - tools/lldb-mi/MICmdCmdTrace.cpp | 10 - tools/lldb-mi/MICmdCmdTrace.h | 10 - tools/lldb-mi/MICmdCmdVar.cpp | 425 +- tools/lldb-mi/MICmdCmdVar.h | 45 +- tools/lldb-mi/MICmdCommands.cpp | 22 +- tools/lldb-mi/MICmdCommands.h | 12 - tools/lldb-mi/MICmdData.cpp | 12 - tools/lldb-mi/MICmdData.h | 12 - tools/lldb-mi/MICmdFactory.cpp | 16 +- tools/lldb-mi/MICmdFactory.h | 12 - tools/lldb-mi/MICmdInterpreter.cpp | 42 +- tools/lldb-mi/MICmdInterpreter.h | 14 +- tools/lldb-mi/MICmdInvoker.cpp | 12 - tools/lldb-mi/MICmdInvoker.h | 12 - tools/lldb-mi/MICmdMgr.cpp | 12 - tools/lldb-mi/MICmdMgr.h | 12 - .../lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp | 12 - tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h | 12 - tools/lldb-mi/MICmnBase.cpp | 12 - tools/lldb-mi/MICmnBase.h | 12 - tools/lldb-mi/MICmnConfig.h | 32 - tools/lldb-mi/MICmnLLDBBroadcaster.cpp | 12 - tools/lldb-mi/MICmnLLDBBroadcaster.h | 12 - tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp | 971 +--- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h | 78 +- .../MICmnLLDBDebugSessionInfoVarObj.cpp | 92 +- .../lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h | 23 +- tools/lldb-mi/MICmnLLDBDebugger.cpp | 144 +- tools/lldb-mi/MICmnLLDBDebugger.h | 21 +- .../lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp | 777 ++- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h | 36 +- tools/lldb-mi/MICmnLLDBProxySBValue.cpp | 20 +- tools/lldb-mi/MICmnLLDBProxySBValue.h | 12 - tools/lldb-mi/MICmnLLDBUtilSBValue.cpp | 440 +- tools/lldb-mi/MICmnLLDBUtilSBValue.h | 40 +- tools/lldb-mi/MICmnLog.cpp | 12 - tools/lldb-mi/MICmnLog.h | 12 - tools/lldb-mi/MICmnLogMediumFile.cpp | 73 +- tools/lldb-mi/MICmnLogMediumFile.h | 19 +- tools/lldb-mi/MICmnMIOutOfBandRecord.cpp | 52 +- tools/lldb-mi/MICmnMIOutOfBandRecord.h | 21 +- tools/lldb-mi/MICmnMIResultRecord.cpp | 14 +- tools/lldb-mi/MICmnMIResultRecord.h | 12 - tools/lldb-mi/MICmnMIValue.cpp | 12 - tools/lldb-mi/MICmnMIValue.h | 12 - tools/lldb-mi/MICmnMIValueConst.cpp | 16 +- tools/lldb-mi/MICmnMIValueConst.h | 12 - tools/lldb-mi/MICmnMIValueList.cpp | 25 +- tools/lldb-mi/MICmnMIValueList.h | 12 - tools/lldb-mi/MICmnMIValueResult.cpp | 18 +- tools/lldb-mi/MICmnMIValueResult.h | 14 +- tools/lldb-mi/MICmnMIValueTuple.cpp | 24 +- tools/lldb-mi/MICmnMIValueTuple.h | 14 +- tools/lldb-mi/MICmnResources.cpp | 64 +- tools/lldb-mi/MICmnResources.h | 44 +- tools/lldb-mi/MICmnStreamStderr.cpp | 12 - tools/lldb-mi/MICmnStreamStderr.h | 12 - tools/lldb-mi/MICmnStreamStdin.cpp | 312 +- tools/lldb-mi/MICmnStreamStdin.h | 72 +- tools/lldb-mi/MICmnStreamStdinLinux.cpp | 225 - tools/lldb-mi/MICmnStreamStdinLinux.h | 72 - tools/lldb-mi/MICmnStreamStdinWindows.cpp | 285 - tools/lldb-mi/MICmnStreamStdinWindows.h | 79 - tools/lldb-mi/MICmnStreamStdout.cpp | 42 +- tools/lldb-mi/MICmnStreamStdout.h | 13 +- tools/lldb-mi/MICmnThreadMgrStd.cpp | 12 - tools/lldb-mi/MICmnThreadMgrStd.h | 12 - tools/lldb-mi/MIDataTypes.h | 13 - tools/lldb-mi/MIDriver.cpp | 507 +- tools/lldb-mi/MIDriver.h | 33 +- tools/lldb-mi/MIDriverBase.cpp | 12 - tools/lldb-mi/MIDriverBase.h | 12 - tools/lldb-mi/MIDriverMain.cpp | 235 +- tools/lldb-mi/MIDriverMgr.cpp | 116 +- tools/lldb-mi/MIDriverMgr.h | 16 +- tools/lldb-mi/MIExtensions.txt | 103 + tools/lldb-mi/MIReadMe.txt | 254 +- tools/lldb-mi/MIUtilDateTimeStd.cpp | 30 +- tools/lldb-mi/MIUtilDateTimeStd.h | 15 +- tools/lldb-mi/MIUtilDebug.cpp | 12 - tools/lldb-mi/MIUtilDebug.h | 12 - tools/lldb-mi/MIUtilFileStd.cpp | 28 +- tools/lldb-mi/MIUtilFileStd.h | 18 +- tools/lldb-mi/MIUtilMapIdToVariant.cpp | 12 - tools/lldb-mi/MIUtilMapIdToVariant.h | 12 - tools/lldb-mi/MIUtilSingletonBase.h | 12 - tools/lldb-mi/MIUtilSingletonHelper.h | 12 - tools/lldb-mi/MIUtilString.cpp | 583 +- tools/lldb-mi/MIUtilString.h | 44 +- tools/lldb-mi/MIUtilSystemLinux.cpp | 14 +- tools/lldb-mi/MIUtilSystemLinux.h | 14 +- tools/lldb-mi/MIUtilSystemOsx.cpp | 12 - tools/lldb-mi/MIUtilSystemOsx.h | 12 - tools/lldb-mi/MIUtilSystemWindows.cpp | 26 +- tools/lldb-mi/MIUtilSystemWindows.h | 12 - tools/lldb-mi/MIUtilTermios.cpp | 71 - tools/lldb-mi/MIUtilTermios.h | 30 - tools/lldb-mi/MIUtilThreadBaseStd.cpp | 43 +- tools/lldb-mi/MIUtilThreadBaseStd.h | 15 +- tools/lldb-mi/MIUtilVariant.cpp | 12 - tools/lldb-mi/MIUtilVariant.h | 12 - tools/lldb-mi/Platform.cpp | 61 +- tools/lldb-mi/Platform.h | 8 +- tools/lldb-server/LLDBServerUtilities.cpp | 67 + tools/lldb-server/LLDBServerUtilities.h | 25 + tools/lldb-server/exports | 0 tools/lldb-server/lldb-gdbserver.cpp | 698 +++ .../lldb-platform.cpp | 202 +- tools/lldb-server/lldb-server.cpp | 76 + 833 files changed, 57658 insertions(+), 29014 deletions(-) create mode 100644 include/lldb/API/SBAttachInfo.h create mode 100644 include/lldb/API/SBLanguageRuntime.h create mode 100644 include/lldb/API/SBVariablesOptions.h create mode 100644 include/lldb/API/SystemInitializerFull.h create mode 100644 include/lldb/Core/CxaDemangle.h create mode 100644 include/lldb/Core/FastDemangle.h rename include/lldb/{lldb-private-log.h => Core/Logging.h} (94%) create mode 100644 include/lldb/Core/ThreadSafeDenseSet.h rename tools/lldb-platform/exports => include/lldb/DataFormatters/VectorType.h (100%) create mode 100644 include/lldb/Host/LockFile.h create mode 100644 include/lldb/Host/LockFileBase.h create mode 100644 include/lldb/Host/Time.h create mode 100644 include/lldb/Host/XML.h create mode 100644 include/lldb/Host/posix/Fcntl.h create mode 100644 include/lldb/Host/posix/LockFilePosix.h create mode 100644 include/lldb/Initialization/SystemInitializer.h create mode 100644 include/lldb/Initialization/SystemInitializerCommon.h create mode 100644 include/lldb/Initialization/SystemLifetimeManager.h create mode 100644 include/lldb/Interpreter/OptionValueLanguage.h create mode 100644 include/lldb/Utility/ConvertEnum.h create mode 100644 include/lldb/Utility/JSON.h create mode 100644 include/lldb/Utility/LLDBAssert.h create mode 100644 include/lldb/Utility/NameMatches.h create mode 100644 source/API/SBAttachInfo.cpp create mode 100644 source/API/SBLanguageRuntime.cpp create mode 100644 source/API/SBVariablesOptions.cpp create mode 100644 source/API/SystemInitializerFull.cpp create mode 100644 source/Commands/CommandObjectBugreport.cpp create mode 100644 source/Commands/CommandObjectBugreport.h create mode 100644 source/Commands/CommandObjectLanguage.cpp create mode 100644 source/Commands/CommandObjectLanguage.h create mode 100644 source/Core/CxaDemangle.cpp rename source/{lldb-log.cpp => Core/Logging.cpp} (97%) create mode 100644 source/DataFormatters/CoreMedia.cpp create mode 100644 source/DataFormatters/VectorType.cpp create mode 100644 source/Host/common/FileSystem.cpp create mode 100644 source/Host/common/LockFileBase.cpp create mode 100644 source/Host/common/XML.cpp create mode 100644 source/Host/posix/LockFilePosix.cpp create mode 100644 source/Initialization/SystemInitializer.cpp create mode 100644 source/Initialization/SystemInitializerCommon.cpp create mode 100644 source/Initialization/SystemLifetimeManager.cpp create mode 100644 source/Interpreter/OptionValueLanguage.cpp create mode 100644 source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp create mode 100644 source/Plugins/ABI/SysV-arm/ABISysV_arm.h create mode 100644 source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp create mode 100644 source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h create mode 100644 source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp create mode 100644 source/Plugins/ABI/SysV-i386/ABISysV_i386.h create mode 100644 source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp create mode 100644 source/Plugins/ABI/SysV-mips/ABISysV_mips.h create mode 100644 source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp create mode 100644 source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h create mode 100644 source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp create mode 100644 source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h create mode 100644 source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp create mode 100644 source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h create mode 100644 source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp create mode 100644 source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h rename source/Plugins/Process/{POSIX => FreeBSD}/POSIXStopInfo.cpp (100%) rename source/Plugins/Process/{POSIX => FreeBSD}/POSIXStopInfo.h (100%) rename source/Plugins/Process/{POSIX => FreeBSD}/POSIXThread.cpp (87%) rename source/Plugins/Process/{POSIX => FreeBSD}/POSIXThread.h (88%) rename source/Plugins/Process/{POSIX => FreeBSD}/ProcessPOSIX.cpp (86%) rename source/Plugins/Process/{POSIX => FreeBSD}/ProcessPOSIX.h (81%) create mode 100644 source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp create mode 100644 source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_arm64.cpp (98%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_arm64.h (100%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_mips64.cpp (99%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_mips64.h (100%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_powerpc.cpp (99%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_powerpc.h (100%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_x86.cpp (99%) rename source/Plugins/Process/{POSIX => FreeBSD}/RegisterContextPOSIXProcessMonitor_x86.h (100%) create mode 100644 source/Plugins/Process/Utility/MipsLinuxSignals.cpp create mode 100644 source/Plugins/Process/Utility/MipsLinuxSignals.h create mode 100644 source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h create mode 100644 source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_arm.h create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_mips.h create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_mips64.h create mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h create mode 100644 source/Plugins/Process/Utility/RegisterInfos_arm.h create mode 100644 source/Plugins/Process/Utility/RegisterInfos_mips.h create mode 100644 source/Plugins/Process/Utility/lldb-arm-register-enums.h create mode 100644 source/Plugins/Process/Utility/lldb-arm64-register-enums.h create mode 100644 source/Plugins/Process/Utility/lldb-mips64-register-enums.h create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h create mode 100644 source/Utility/ConvertEnum.cpp create mode 100644 source/Utility/JSON.cpp create mode 100644 source/Utility/LLDBAssert.cpp create mode 100644 source/Utility/ModuleCache.cpp create mode 100644 source/Utility/ModuleCache.h create mode 100644 source/Utility/NameMatches.cpp create mode 100644 tools/argdumper/argdumper.cpp create mode 100644 tools/argdumper/exports delete mode 100644 tools/lldb-mi/Driver.cpp delete mode 100644 tools/lldb-mi/Driver.h create mode 100644 tools/lldb-mi/MICmdArgValPrintValues.cpp create mode 100644 tools/lldb-mi/MICmdArgValPrintValues.h create mode 100644 tools/lldb-mi/MICmdCmdGdbShow.cpp create mode 100644 tools/lldb-mi/MICmdCmdGdbShow.h create mode 100644 tools/lldb-mi/MICmdCmdSymbol.cpp create mode 100644 tools/lldb-mi/MICmdCmdSymbol.h delete mode 100644 tools/lldb-mi/MICmnStreamStdinLinux.cpp delete mode 100644 tools/lldb-mi/MICmnStreamStdinLinux.h delete mode 100644 tools/lldb-mi/MICmnStreamStdinWindows.cpp delete mode 100644 tools/lldb-mi/MICmnStreamStdinWindows.h create mode 100644 tools/lldb-mi/MIExtensions.txt delete mode 100644 tools/lldb-mi/MIUtilTermios.cpp delete mode 100644 tools/lldb-mi/MIUtilTermios.h create mode 100644 tools/lldb-server/LLDBServerUtilities.cpp create mode 100644 tools/lldb-server/LLDBServerUtilities.h create mode 100644 tools/lldb-server/exports create mode 100644 tools/lldb-server/lldb-gdbserver.cpp rename tools/{lldb-platform => lldb-server}/lldb-platform.cpp (60%) create mode 100644 tools/lldb-server/lldb-server.cpp diff --git a/include/lldb/API/LLDB.h b/include/lldb/API/LLDB.h index 4026b2b61ba8..66e095395f13 100644 --- a/include/lldb/API/LLDB.h +++ b/include/lldb/API/LLDB.h @@ -52,5 +52,6 @@ #include "lldb/API/SBType.h" #include "lldb/API/SBValue.h" #include "lldb/API/SBValueList.h" +#include "lldb/API/SBVariablesOptions.h" #endif // LLDB_LLDB_h_ diff --git a/include/lldb/API/SBAddress.h b/include/lldb/API/SBAddress.h index c2d07b6e9bcc..4cbbee9fd132 100644 --- a/include/lldb/API/SBAddress.h +++ b/include/lldb/API/SBAddress.h @@ -15,7 +15,7 @@ namespace lldb { -class SBAddress +class LLDB_API SBAddress { public: diff --git a/include/lldb/API/SBAttachInfo.h b/include/lldb/API/SBAttachInfo.h new file mode 100644 index 000000000000..712150e128be --- /dev/null +++ b/include/lldb/API/SBAttachInfo.h @@ -0,0 +1,149 @@ +//===-- SBAttachInfo.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBAttachInfo_h_ +#define LLDB_SBAttachInfo_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBTarget; + +class LLDB_API SBAttachInfo +{ +public: + SBAttachInfo (); + + SBAttachInfo (lldb::pid_t pid); + + SBAttachInfo (const char *path, bool wait_for); + + SBAttachInfo (const SBAttachInfo &rhs); + + ~SBAttachInfo(); + + SBAttachInfo & + operator = (const SBAttachInfo &rhs); + + lldb::pid_t + GetProcessID (); + + void + SetProcessID (lldb::pid_t pid); + + void + SetExecutable (const char *path); + + void + SetExecutable (lldb::SBFileSpec exe_file); + + bool + GetWaitForLaunch (); + + void + SetWaitForLaunch (bool b); + + bool + GetIgnoreExisting (); + + void + SetIgnoreExisting (bool b); + + uint32_t + GetResumeCount (); + + void + SetResumeCount (uint32_t c); + + const char * + GetProcessPluginName (); + + void + SetProcessPluginName (const char *plugin_name); + + uint32_t + GetUserID(); + + uint32_t + GetGroupID(); + + bool + UserIDIsValid (); + + bool + GroupIDIsValid (); + + void + SetUserID (uint32_t uid); + + void + SetGroupID (uint32_t gid); + + uint32_t + GetEffectiveUserID(); + + uint32_t + GetEffectiveGroupID(); + + bool + EffectiveUserIDIsValid (); + + bool + EffectiveGroupIDIsValid (); + + void + SetEffectiveUserID (uint32_t uid); + + void + SetEffectiveGroupID (uint32_t gid); + + lldb::pid_t + GetParentProcessID (); + + void + SetParentProcessID (lldb::pid_t pid); + + bool + ParentProcessIDIsValid(); + + //---------------------------------------------------------------------- + /// Get the listener that will be used to receive process events. + /// + /// If no listener has been set via a call to + /// SBLaunchInfo::SetListener(), then an invalid SBListener will be + /// returned (SBListener::IsValid() will return false). If a listener + /// has been set, then the valid listener object will be returned. + //---------------------------------------------------------------------- + SBListener + GetListener (); + + //---------------------------------------------------------------------- + /// Set the listener that will be used to receive process events. + /// + /// By default the SBDebugger, which has a listener, that the SBTarget + /// belongs to will listen for the process events. Calling this function + /// allows a different listener to be used to listen for process events. + //---------------------------------------------------------------------- + void + SetListener (SBListener &listener); + + +protected: + friend class SBTarget; + + lldb_private::ProcessAttachInfo & + ref (); + + ProcessAttachInfoSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBAttachInfo_h_ diff --git a/include/lldb/API/SBBlock.h b/include/lldb/API/SBBlock.h index b8e61fc6eb27..a18eab02088b 100644 --- a/include/lldb/API/SBBlock.h +++ b/include/lldb/API/SBBlock.h @@ -17,7 +17,7 @@ namespace lldb { -class SBBlock +class LLDB_API SBBlock { public: diff --git a/include/lldb/API/SBBreakpoint.h b/include/lldb/API/SBBreakpoint.h index 20a97a1fb5a0..c244ab8a9b48 100644 --- a/include/lldb/API/SBBreakpoint.h +++ b/include/lldb/API/SBBreakpoint.h @@ -14,7 +14,7 @@ namespace lldb { -class SBBreakpoint +class LLDB_API SBBreakpoint { public: diff --git a/include/lldb/API/SBBreakpointLocation.h b/include/lldb/API/SBBreakpointLocation.h index fd9f246de4ff..ab7049739c0b 100644 --- a/include/lldb/API/SBBreakpointLocation.h +++ b/include/lldb/API/SBBreakpointLocation.h @@ -15,7 +15,7 @@ namespace lldb { -class SBBreakpointLocation +class LLDB_API SBBreakpointLocation { public: @@ -101,9 +101,7 @@ class SBBreakpointLocation private: friend class SBBreakpoint; -#ifndef LLDB_DISABLE_PYTHON - friend class lldb_private::ScriptInterpreterPython; -#endif + void SetLocation (const lldb::BreakpointLocationSP &break_loc_sp); diff --git a/include/lldb/API/SBBroadcaster.h b/include/lldb/API/SBBroadcaster.h index 7b32d85faa0f..28b6686b79b3 100644 --- a/include/lldb/API/SBBroadcaster.h +++ b/include/lldb/API/SBBroadcaster.h @@ -14,7 +14,7 @@ namespace lldb { -class SBBroadcaster +class LLDB_API SBBroadcaster { public: SBBroadcaster (); diff --git a/include/lldb/API/SBCommandInterpreter.h b/include/lldb/API/SBCommandInterpreter.h index 947e39164140..235a2f3ea603 100644 --- a/include/lldb/API/SBCommandInterpreter.h +++ b/include/lldb/API/SBCommandInterpreter.h @@ -15,7 +15,7 @@ namespace lldb { -class SBCommandInterpreterRunOptions +class LLDB_API SBCommandInterpreterRunOptions { friend class SBDebugger; friend class SBCommandInterpreter; @@ -94,6 +94,9 @@ class SBCommandInterpreter static const char * GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type); + + static bool + EventIsCommandInterpreterEvent (const lldb::SBEvent &event); bool IsValid() const; @@ -216,6 +219,19 @@ class SBCommandInterpreter const char * GetIOHandlerControlSequence(char ch); + bool + GetPromptOnQuit(); + + void + SetPromptOnQuit(bool b); + + //---------------------------------------------------------------------- + /// Resolve the command just as HandleCommand would, expanding abbreviations + /// and aliases. If successful, result->GetOutput has the full expansion. + //---------------------------------------------------------------------- + void + ResolveCommand(const char *command_line, SBCommandReturnObject &result); + protected: lldb_private::CommandInterpreter & @@ -266,6 +282,21 @@ class SBCommand const char* GetHelp (); + const char* + GetHelpLong (); + + void + SetHelp (const char*); + + void + SetHelpLong (const char*); + + uint32_t + GetFlags (); + + void + SetFlags (uint32_t flags); + lldb::SBCommand AddMultiwordCommand (const char* name, const char* help = NULL); diff --git a/include/lldb/API/SBCommandReturnObject.h b/include/lldb/API/SBCommandReturnObject.h index f2d274802330..c51d6bc8d2d5 100644 --- a/include/lldb/API/SBCommandReturnObject.h +++ b/include/lldb/API/SBCommandReturnObject.h @@ -16,7 +16,7 @@ namespace lldb { -class SBCommandReturnObject +class LLDB_API SBCommandReturnObject { public: diff --git a/include/lldb/API/SBCommunication.h b/include/lldb/API/SBCommunication.h index ecaaa3523c91..c4b2709de8ab 100644 --- a/include/lldb/API/SBCommunication.h +++ b/include/lldb/API/SBCommunication.h @@ -15,10 +15,11 @@ namespace lldb { -class SBCommunication +class LLDB_API SBCommunication { public: - enum { + FLAGS_ANONYMOUS_ENUM() + { eBroadcastBitDisconnected = (1 << 0), ///< Sent when the communications connection is lost. eBroadcastBitReadThreadGotBytes = (1 << 1), ///< Sent by the read thread when bytes become available. eBroadcastBitReadThreadDidExit = (1 << 2), ///< Sent by the read thread when it exits to inform clients. diff --git a/include/lldb/API/SBCompileUnit.h b/include/lldb/API/SBCompileUnit.h index e2c216445d94..a53d556679c4 100644 --- a/include/lldb/API/SBCompileUnit.h +++ b/include/lldb/API/SBCompileUnit.h @@ -15,7 +15,7 @@ namespace lldb { -class SBCompileUnit +class LLDB_API SBCompileUnit { public: diff --git a/include/lldb/API/SBData.h b/include/lldb/API/SBData.h index e7656a52d9c2..a2bd72fad570 100644 --- a/include/lldb/API/SBData.h +++ b/include/lldb/API/SBData.h @@ -14,7 +14,7 @@ namespace lldb { -class SBData +class LLDB_API SBData { public: diff --git a/include/lldb/API/SBDebugger.h b/include/lldb/API/SBDebugger.h index 6e43e12f7b16..4f2c1d7f8756 100644 --- a/include/lldb/API/SBDebugger.h +++ b/include/lldb/API/SBDebugger.h @@ -18,7 +18,7 @@ namespace lldb { -class SBInputReader +class LLDB_API SBInputReader { public: SBInputReader(); @@ -28,7 +28,7 @@ class SBInputReader bool IsActive() const; }; -class SBDebugger +class LLDB_API SBDebugger { public: diff --git a/include/lldb/API/SBDeclaration.h b/include/lldb/API/SBDeclaration.h index 190026c0d2d0..5461a1f15c2e 100644 --- a/include/lldb/API/SBDeclaration.h +++ b/include/lldb/API/SBDeclaration.h @@ -15,7 +15,7 @@ namespace lldb { - class SBDeclaration + class LLDB_API SBDeclaration { public: diff --git a/include/lldb/API/SBDefines.h b/include/lldb/API/SBDefines.h index b59b79580910..09bea502dd01 100644 --- a/include/lldb/API/SBDefines.h +++ b/include/lldb/API/SBDefines.h @@ -55,6 +55,8 @@ class LLDB_API SBFunction; class LLDB_API SBHostOS; class LLDB_API SBInstruction; class LLDB_API SBInstructionList; +class LLDB_API SBLanguageRuntime; +class LLDB_API SBLaunchInfo; class LLDB_API SBLineEntry; class LLDB_API SBListener; class LLDB_API SBModule; @@ -90,6 +92,7 @@ class LLDB_API SBTypeSynthetic; class LLDB_API SBTypeList; class LLDB_API SBValue; class LLDB_API SBValueList; +class LLDB_API SBVariablesOptions; class LLDB_API SBWatchpoint; class LLDB_API SBUnixSignals; diff --git a/include/lldb/API/SBError.h b/include/lldb/API/SBError.h index b9908658c5bc..afdec0d3826d 100644 --- a/include/lldb/API/SBError.h +++ b/include/lldb/API/SBError.h @@ -14,7 +14,7 @@ namespace lldb { -class SBError { +class LLDB_API SBError { public: SBError (); diff --git a/include/lldb/API/SBEvent.h b/include/lldb/API/SBEvent.h index 1706d0c009b9..975c365f5916 100644 --- a/include/lldb/API/SBEvent.h +++ b/include/lldb/API/SBEvent.h @@ -20,7 +20,7 @@ namespace lldb { class SBBroadcaster; -class SBEvent +class LLDB_API SBEvent { public: SBEvent(); @@ -78,6 +78,7 @@ class SBEvent friend class SBBreakpoint; friend class SBDebugger; friend class SBProcess; + friend class SBTarget; friend class SBThread; friend class SBWatchpoint; diff --git a/include/lldb/API/SBExecutionContext.h b/include/lldb/API/SBExecutionContext.h index 9d889139f5cb..1d64497ae867 100644 --- a/include/lldb/API/SBExecutionContext.h +++ b/include/lldb/API/SBExecutionContext.h @@ -18,7 +18,7 @@ namespace lldb { -class SBExecutionContext +class LLDB_API SBExecutionContext { friend class SBCommandInterpreter; diff --git a/include/lldb/API/SBExpressionOptions.h b/include/lldb/API/SBExpressionOptions.h index c3592880c46a..ed2f9187b3e0 100644 --- a/include/lldb/API/SBExpressionOptions.h +++ b/include/lldb/API/SBExpressionOptions.h @@ -17,7 +17,7 @@ namespace lldb { -class SBExpressionOptions +class LLDB_API SBExpressionOptions { public: SBExpressionOptions(); @@ -105,6 +105,12 @@ class SBExpressionOptions void SetSuppressPersistentResult (bool b = false); + const char * + GetPrefix () const; + + void + SetPrefix (const char *prefix); + protected: SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options); diff --git a/include/lldb/API/SBFileSpec.h b/include/lldb/API/SBFileSpec.h index 1eee3d10367c..d6f38f5b2d74 100644 --- a/include/lldb/API/SBFileSpec.h +++ b/include/lldb/API/SBFileSpec.h @@ -14,7 +14,7 @@ namespace lldb { -class SBFileSpec +class LLDB_API SBFileSpec { public: SBFileSpec (); diff --git a/include/lldb/API/SBFileSpecList.h b/include/lldb/API/SBFileSpecList.h index 734e7d4d35cc..ff429a1815be 100644 --- a/include/lldb/API/SBFileSpecList.h +++ b/include/lldb/API/SBFileSpecList.h @@ -14,7 +14,7 @@ namespace lldb { -class SBFileSpecList +class LLDB_API SBFileSpecList { public: SBFileSpecList (); diff --git a/include/lldb/API/SBFrame.h b/include/lldb/API/SBFrame.h index b93e36afecdf..2ca9e062490d 100644 --- a/include/lldb/API/SBFrame.h +++ b/include/lldb/API/SBFrame.h @@ -15,7 +15,7 @@ namespace lldb { -class SBFrame +class LLDB_API SBFrame { public: SBFrame (); @@ -25,7 +25,7 @@ class SBFrame const lldb::SBFrame & operator =(const lldb::SBFrame &rhs); - ~SBFrame(); + ~SBFrame(); bool IsEqual (const lldb::SBFrame &that) const; @@ -36,6 +36,9 @@ class SBFrame uint32_t GetFrameID () const; + lldb::addr_t + GetCFA () const; + lldb::addr_t GetPC () const; @@ -88,12 +91,18 @@ class SBFrame const char * GetFunctionName(); + const char * + GetFunctionName() const; + /// Return true if this frame represents an inlined function. /// /// See also GetFunctionName(). bool IsInlined(); - + + bool + IsInlined() const; + /// The version that doesn't supply a 'use_dynamic' value will use the /// target's default. lldb::SBValue @@ -156,6 +165,9 @@ class SBFrame bool in_scope_only, lldb::DynamicValueType use_dynamic); + lldb::SBValueList + GetVariables (const lldb::SBVariablesOptions& options); + lldb::SBValueList GetRegisters (); @@ -210,9 +222,6 @@ class SBFrame friend class SBInstruction; friend class SBThread; friend class SBValue; -#ifndef LLDB_DISABLE_PYTHON - friend class lldb_private::ScriptInterpreterPython; -#endif lldb::StackFrameSP GetFrameSP() const; diff --git a/include/lldb/API/SBFunction.h b/include/lldb/API/SBFunction.h index 1b0d53d11736..7d578393eb2c 100644 --- a/include/lldb/API/SBFunction.h +++ b/include/lldb/API/SBFunction.h @@ -16,7 +16,7 @@ namespace lldb { -class SBFunction +class LLDB_API SBFunction { public: diff --git a/include/lldb/API/SBHostOS.h b/include/lldb/API/SBHostOS.h index 7ab22caaaad9..d9bc97365632 100644 --- a/include/lldb/API/SBHostOS.h +++ b/include/lldb/API/SBHostOS.h @@ -15,7 +15,7 @@ namespace lldb { -class SBHostOS +class LLDB_API SBHostOS { public: diff --git a/include/lldb/API/SBInstruction.h b/include/lldb/API/SBInstruction.h index aad2d87f4f33..c4bded595761 100644 --- a/include/lldb/API/SBInstruction.h +++ b/include/lldb/API/SBInstruction.h @@ -20,7 +20,7 @@ namespace lldb { -class SBInstruction +class LLDB_API SBInstruction { public: diff --git a/include/lldb/API/SBInstructionList.h b/include/lldb/API/SBInstructionList.h index 944e144a1480..8ef163796629 100644 --- a/include/lldb/API/SBInstructionList.h +++ b/include/lldb/API/SBInstructionList.h @@ -16,7 +16,7 @@ namespace lldb { -class SBInstructionList +class LLDB_API SBInstructionList { public: diff --git a/include/lldb/API/SBLanguageRuntime.h b/include/lldb/API/SBLanguageRuntime.h new file mode 100644 index 000000000000..898604c496fa --- /dev/null +++ b/include/lldb/API/SBLanguageRuntime.h @@ -0,0 +1,29 @@ +//===-- SBLanguageRuntime.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBLanguageRuntime_h_ +#define LLDB_SBLanguageRuntime_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBLanguageRuntime +{ +public: + static lldb::LanguageType + GetLanguageTypeFromString (const char *string); + + static const char * + GetNameForLanguageType (lldb::LanguageType language); +}; + +} // namespace lldb + +#endif // LLDB_SBLanguageRuntime_h_ diff --git a/include/lldb/API/SBLaunchInfo.h b/include/lldb/API/SBLaunchInfo.h index a5921ab90d48..68c0f386acde 100644 --- a/include/lldb/API/SBLaunchInfo.h +++ b/include/lldb/API/SBLaunchInfo.h @@ -17,7 +17,7 @@ namespace lldb { class SBPlatform; class SBTarget; -class SBLaunchInfo +class LLDB_API SBLaunchInfo { public: SBLaunchInfo (const char **argv); @@ -140,7 +140,13 @@ class SBLaunchInfo void SetShell (const char * path); - + + bool + GetShellExpandArguments (); + + void + SetShellExpandArguments (bool glob); + uint32_t GetResumeCount (); @@ -178,6 +184,9 @@ class SBLaunchInfo lldb_private::ProcessLaunchInfo & ref (); + const lldb_private::ProcessLaunchInfo & + ref () const; + ProcessLaunchInfoSP m_opaque_sp; }; diff --git a/include/lldb/API/SBLineEntry.h b/include/lldb/API/SBLineEntry.h index 2d099a297980..8311bbbafc90 100644 --- a/include/lldb/API/SBLineEntry.h +++ b/include/lldb/API/SBLineEntry.h @@ -16,7 +16,7 @@ namespace lldb { -class SBLineEntry +class LLDB_API SBLineEntry { public: diff --git a/include/lldb/API/SBListener.h b/include/lldb/API/SBListener.h index 58a8fe9a55b7..924f8109f638 100644 --- a/include/lldb/API/SBListener.h +++ b/include/lldb/API/SBListener.h @@ -14,7 +14,7 @@ namespace lldb { -class SBListener +class LLDB_API SBListener { public: SBListener (); diff --git a/include/lldb/API/SBModule.h b/include/lldb/API/SBModule.h index e85654bccc72..4030d2b21797 100644 --- a/include/lldb/API/SBModule.h +++ b/include/lldb/API/SBModule.h @@ -18,7 +18,7 @@ namespace lldb { -class SBModule +class LLDB_API SBModule { public: @@ -106,7 +106,7 @@ class SBModule /// or "./usr/lib", then the install path will be resolved using /// the platform's current working directory as the base path. /// - /// @param[in] + /// @param[in] file /// A file specification object. //------------------------------------------------------------------ bool @@ -318,6 +318,23 @@ class SBModule GetVersion (uint32_t *versions, uint32_t num_versions); + //------------------------------------------------------------------ + /// Get accessor for the symbol file specification. + /// + /// When debugging an object file an additional debug information can + /// be provided in separate file. Therefore if you debugging something + /// like '/usr/lib/liba.dylib' then debug information can be located + /// in folder like '/usr/lib/liba.dylib.dSYM/'. + /// + /// @return + /// A const reference to the file specification object. + //------------------------------------------------------------------ + lldb::SBFileSpec + GetSymbolFileSpec() const; + + lldb::SBAddress + GetObjectFileHeaderAddress() const; + private: friend class SBAddress; friend class SBFrame; diff --git a/include/lldb/API/SBModuleSpec.h b/include/lldb/API/SBModuleSpec.h index a615e017cbc8..d533de3c7bce 100644 --- a/include/lldb/API/SBModuleSpec.h +++ b/include/lldb/API/SBModuleSpec.h @@ -15,7 +15,7 @@ namespace lldb { -class SBModuleSpec +class LLDB_API SBModuleSpec { public: diff --git a/include/lldb/API/SBPlatform.h b/include/lldb/API/SBPlatform.h index 42b2d0492895..db4a754103ca 100644 --- a/include/lldb/API/SBPlatform.h +++ b/include/lldb/API/SBPlatform.h @@ -21,7 +21,7 @@ namespace lldb { class SBLaunchInfo; - class SBPlatformConnectOptions + class LLDB_API SBPlatformConnectOptions { public: SBPlatformConnectOptions (const char *url); @@ -59,7 +59,7 @@ namespace lldb { PlatformConnectOptions *m_opaque_ptr; }; - class SBPlatformShellCommand + class LLDB_API SBPlatformShellCommand { public: SBPlatformShellCommand (const char *shell_command); @@ -104,7 +104,7 @@ namespace lldb { PlatformShellCommand *m_opaque_ptr; }; - class SBPlatform + class LLDB_API SBPlatform { public: diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h index 3d6e49c4821d..71bca4fc697a 100644 --- a/include/lldb/API/SBProcess.h +++ b/include/lldb/API/SBProcess.h @@ -20,13 +20,13 @@ namespace lldb { class SBEvent; -class SBProcess +class LLDB_API SBProcess { public: //------------------------------------------------------------------ /// Broadcaster event bits definitions. //------------------------------------------------------------------ - enum + FLAGS_ANONYMOUS_ENUM() { eBroadcastBitStateChanged = (1 << 0), eBroadcastBitInterrupt = (1 << 1), @@ -229,7 +229,22 @@ class SBProcess uint32_t GetStopID(bool include_expression_stops = false); - + + //------------------------------------------------------------------ + /// Gets the stop event corresponding to stop ID. + // + /// Note that it wasn't fully implemented and tracks only the stop + /// event for the last natural stop ID. + /// + /// @param [in] stop_id + /// The ID of the stop event to return. + /// + /// @return + /// The stop event corresponding to stop ID. + //------------------------------------------------------------------ + lldb::SBEvent + GetStopEventForStopID(uint32_t stop_id); + size_t ReadMemory (addr_t addr, void *buf, size_t size, lldb::SBError &error); @@ -260,6 +275,9 @@ class SBProcess static lldb::SBProcess GetProcessFromEvent (const lldb::SBEvent &event); + + static bool + GetInterruptedFromEvent (const lldb::SBEvent &event); static bool EventIsProcessEvent (const lldb::SBEvent &event); diff --git a/include/lldb/API/SBQueue.h b/include/lldb/API/SBQueue.h index fbb1952902f8..2f453cddd5d1 100644 --- a/include/lldb/API/SBQueue.h +++ b/include/lldb/API/SBQueue.h @@ -17,7 +17,7 @@ namespace lldb { -class SBQueue +class LLDB_API SBQueue { public: SBQueue (); diff --git a/include/lldb/API/SBQueueItem.h b/include/lldb/API/SBQueueItem.h index c90f36eeb573..9426a53b2376 100644 --- a/include/lldb/API/SBQueueItem.h +++ b/include/lldb/API/SBQueueItem.h @@ -15,7 +15,7 @@ namespace lldb { -class SBQueueItem +class LLDB_API SBQueueItem { public: SBQueueItem (); diff --git a/include/lldb/API/SBSection.h b/include/lldb/API/SBSection.h index 5a49049502fd..0a22413b5b9c 100644 --- a/include/lldb/API/SBSection.h +++ b/include/lldb/API/SBSection.h @@ -15,7 +15,7 @@ namespace lldb { -class SBSection +class LLDB_API SBSection { public: diff --git a/include/lldb/API/SBSourceManager.h b/include/lldb/API/SBSourceManager.h index 5b52c49ff3ee..6e7358f16e77 100644 --- a/include/lldb/API/SBSourceManager.h +++ b/include/lldb/API/SBSourceManager.h @@ -16,7 +16,7 @@ namespace lldb { -class SBSourceManager +class LLDB_API SBSourceManager { public: SBSourceManager (const SBDebugger &debugger); diff --git a/include/lldb/API/SBStream.h b/include/lldb/API/SBStream.h index cd33bfda32ba..2b25cd2c68f2 100644 --- a/include/lldb/API/SBStream.h +++ b/include/lldb/API/SBStream.h @@ -16,7 +16,7 @@ namespace lldb { -class SBStream +class LLDB_API SBStream { public: diff --git a/include/lldb/API/SBStringList.h b/include/lldb/API/SBStringList.h index 9d0be6e8a741..e0e58f765c6d 100644 --- a/include/lldb/API/SBStringList.h +++ b/include/lldb/API/SBStringList.h @@ -14,7 +14,7 @@ namespace lldb { -class SBStringList +class LLDB_API SBStringList { public: diff --git a/include/lldb/API/SBSymbol.h b/include/lldb/API/SBSymbol.h index 0a528a9ac96f..3d259a2c20c6 100644 --- a/include/lldb/API/SBSymbol.h +++ b/include/lldb/API/SBSymbol.h @@ -17,7 +17,7 @@ namespace lldb { -class SBSymbol +class LLDB_API SBSymbol { public: diff --git a/include/lldb/API/SBSymbolContext.h b/include/lldb/API/SBSymbolContext.h index fee2d19179d0..24c2ce9a1d6e 100644 --- a/include/lldb/API/SBSymbolContext.h +++ b/include/lldb/API/SBSymbolContext.h @@ -20,7 +20,7 @@ namespace lldb { -class SBSymbolContext +class LLDB_API SBSymbolContext { public: SBSymbolContext (); diff --git a/include/lldb/API/SBSymbolContextList.h b/include/lldb/API/SBSymbolContextList.h index 6cc78e472c6f..79dcccdcbf84 100644 --- a/include/lldb/API/SBSymbolContextList.h +++ b/include/lldb/API/SBSymbolContextList.h @@ -15,7 +15,7 @@ namespace lldb { -class SBSymbolContextList +class LLDB_API SBSymbolContextList { public: SBSymbolContextList (); diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h index 322cf04159ff..dcca4e7b3a19 100644 --- a/include/lldb/API/SBTarget.h +++ b/include/lldb/API/SBTarget.h @@ -12,6 +12,7 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBAddress.h" +#include "lldb/API/SBAttachInfo.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBFileSpecList.h" @@ -25,135 +26,7 @@ namespace lldb { class SBPlatform; -class SBAttachInfo -{ -public: - SBAttachInfo (); - - SBAttachInfo (lldb::pid_t pid); - - SBAttachInfo (const char *path, bool wait_for); - - SBAttachInfo (const SBAttachInfo &rhs); - - ~SBAttachInfo(); - - SBAttachInfo & - operator = (const SBAttachInfo &rhs); - - lldb::pid_t - GetProcessID (); - - void - SetProcessID (lldb::pid_t pid); - - void - SetExecutable (const char *path); - - void - SetExecutable (lldb::SBFileSpec exe_file); - - bool - GetWaitForLaunch (); - - void - SetWaitForLaunch (bool b); - - bool - GetIgnoreExisting (); - - void - SetIgnoreExisting (bool b); - - uint32_t - GetResumeCount (); - - void - SetResumeCount (uint32_t c); - - const char * - GetProcessPluginName (); - - void - SetProcessPluginName (const char *plugin_name); - - uint32_t - GetUserID(); - - uint32_t - GetGroupID(); - - bool - UserIDIsValid (); - - bool - GroupIDIsValid (); - - void - SetUserID (uint32_t uid); - - void - SetGroupID (uint32_t gid); - - uint32_t - GetEffectiveUserID(); - - uint32_t - GetEffectiveGroupID(); - - bool - EffectiveUserIDIsValid (); - - bool - EffectiveGroupIDIsValid (); - - void - SetEffectiveUserID (uint32_t uid); - - void - SetEffectiveGroupID (uint32_t gid); - - lldb::pid_t - GetParentProcessID (); - - void - SetParentProcessID (lldb::pid_t pid); - - bool - ParentProcessIDIsValid(); - - //---------------------------------------------------------------------- - /// Get the listener that will be used to receive process events. - /// - /// If no listener has been set via a call to - /// SBLaunchInfo::SetListener(), then an invalid SBListener will be - /// returned (SBListener::IsValid() will return false). If a listener - /// has been set, then the valid listener object will be returned. - //---------------------------------------------------------------------- - SBListener - GetListener (); - - //---------------------------------------------------------------------- - /// Set the listener that will be used to receive process events. - /// - /// By default the SBDebugger, which has a listener, that the SBTarget - /// belongs to will listen for the process events. Calling this function - /// allows a different listener to be used to listen for process events. - //---------------------------------------------------------------------- - void - SetListener (SBListener &listener); - - -protected: - friend class SBTarget; - - lldb_private::ProcessAttachInfo & - ref (); - - ProcessAttachInfoSP m_opaque_sp; -}; - -class SBTarget +class LLDB_API SBTarget { public: //------------------------------------------------------------------ @@ -187,7 +60,19 @@ class SBTarget bool IsValid() const; + + static bool + EventIsTargetEvent (const lldb::SBEvent &event); + + static lldb::SBTarget + GetTargetFromEvent (const lldb::SBEvent &event); + static uint32_t + GetNumModulesFromEvent (const lldb::SBEvent &event); + + static lldb::SBModule + GetModuleAtIndexFromEvent (const uint32_t idx, const lldb::SBEvent &event); + static const char * GetBroadcasterClassName (); @@ -273,7 +158,7 @@ class SBTarget /// @param[in] stop_at_entry /// If false do not stop the inferior at the entry point. /// - /// @param[out] + /// @param[out] error /// An error object. Contains the reason if there is some failure. /// /// @return @@ -344,7 +229,7 @@ class SBTarget /// @param[in] pid /// The process ID to attach to. /// - /// @param[out] + /// @param[out] error /// An error explaining what went wrong if attach fails. /// /// @return @@ -378,7 +263,7 @@ class SBTarget /// @param[in] wait_for /// If true wait for a new instance of 'name' to be launched. /// - /// @param[out] + /// @param[out] error /// An error explaining what went wrong if attach fails. /// /// @return @@ -405,7 +290,7 @@ class SBTarget /// @param[in] plugin_name /// The plugin name to be used; can be NULL. /// - /// @param[out] + /// @param[out] error /// An error explaining what went wrong if the connect fails. /// /// @return @@ -764,13 +649,13 @@ class SBTarget lldb::SBBreakpoint BreakpointCreateBySourceRegex (const char *source_regex, - const lldb::SBFileSpec &source_file, + const SBFileSpec &source_file, const char *module_name = NULL); lldb::SBBreakpoint - BreakpointCreateBySourceRegex (const char *source_regex, - const SBFileSpecList &module_list, - const lldb::SBFileSpecList &source_file); + BreakpointCreateBySourceRegex (const char *source_regex, + const SBFileSpecList &module_list, + const SBFileSpecList &source_file); lldb::SBBreakpoint BreakpointCreateForException (lldb::LanguageType language, @@ -888,6 +773,12 @@ class SBTarget lldb::addr_t GetStackRedZoneSize(); + + lldb::SBLaunchInfo + GetLaunchInfo () const; + + void + SetLaunchInfo (const lldb::SBLaunchInfo &launch_info); protected: friend class SBAddress; diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h index db15f651f2d5..2c45fa8d5120 100644 --- a/include/lldb/API/SBThread.h +++ b/include/lldb/API/SBThread.h @@ -18,7 +18,7 @@ namespace lldb { class SBFrame; -class SBThread +class LLDB_API SBThread { public: enum diff --git a/include/lldb/API/SBThreadCollection.h b/include/lldb/API/SBThreadCollection.h index b13cbd938e28..996ee3cd22aa 100644 --- a/include/lldb/API/SBThreadCollection.h +++ b/include/lldb/API/SBThreadCollection.h @@ -14,7 +14,7 @@ namespace lldb { -class SBThreadCollection +class LLDB_API SBThreadCollection { public: diff --git a/include/lldb/API/SBThreadPlan.h b/include/lldb/API/SBThreadPlan.h index e53942d65fa8..9cc0d0b89bb5 100644 --- a/include/lldb/API/SBThreadPlan.h +++ b/include/lldb/API/SBThreadPlan.h @@ -16,7 +16,7 @@ namespace lldb { -class SBThreadPlan +class LLDB_API SBThreadPlan { friend class lldb_private::ThreadPlan; diff --git a/include/lldb/API/SBType.h b/include/lldb/API/SBType.h index 7990fc0696a9..01f0c6afc795 100644 --- a/include/lldb/API/SBType.h +++ b/include/lldb/API/SBType.h @@ -16,7 +16,7 @@ namespace lldb { class SBTypeList; -class SBTypeMember +class LLDB_API SBTypeMember { public: SBTypeMember (); diff --git a/include/lldb/API/SBTypeCategory.h b/include/lldb/API/SBTypeCategory.h index f123e931e17d..30c338b28a46 100644 --- a/include/lldb/API/SBTypeCategory.h +++ b/include/lldb/API/SBTypeCategory.h @@ -14,7 +14,7 @@ namespace lldb { - class SBTypeCategory + class LLDB_API SBTypeCategory { public: diff --git a/include/lldb/API/SBTypeEnumMember.h b/include/lldb/API/SBTypeEnumMember.h index 75c9917989c2..b141ba0a6bb0 100644 --- a/include/lldb/API/SBTypeEnumMember.h +++ b/include/lldb/API/SBTypeEnumMember.h @@ -15,7 +15,7 @@ namespace lldb { -class SBTypeEnumMember +class LLDB_API SBTypeEnumMember { public: SBTypeEnumMember (); diff --git a/include/lldb/API/SBTypeFilter.h b/include/lldb/API/SBTypeFilter.h index 016954943e28..f030b6a99b60 100644 --- a/include/lldb/API/SBTypeFilter.h +++ b/include/lldb/API/SBTypeFilter.h @@ -14,7 +14,7 @@ namespace lldb { - class SBTypeFilter + class LLDB_API SBTypeFilter { public: diff --git a/include/lldb/API/SBTypeFormat.h b/include/lldb/API/SBTypeFormat.h index eb45ff2b0eba..c24641ac15f5 100644 --- a/include/lldb/API/SBTypeFormat.h +++ b/include/lldb/API/SBTypeFormat.h @@ -14,7 +14,7 @@ namespace lldb { -class SBTypeFormat +class LLDB_API SBTypeFormat { public: diff --git a/include/lldb/API/SBTypeNameSpecifier.h b/include/lldb/API/SBTypeNameSpecifier.h index 19d1988aa0c5..71700a7123d5 100644 --- a/include/lldb/API/SBTypeNameSpecifier.h +++ b/include/lldb/API/SBTypeNameSpecifier.h @@ -14,7 +14,7 @@ namespace lldb { - class SBTypeNameSpecifier + class LLDB_API SBTypeNameSpecifier { public: diff --git a/include/lldb/API/SBTypeSummary.h b/include/lldb/API/SBTypeSummary.h index 220451e6d70b..9b367ba5f982 100644 --- a/include/lldb/API/SBTypeSummary.h +++ b/include/lldb/API/SBTypeSummary.h @@ -15,7 +15,7 @@ #ifndef LLDB_DISABLE_PYTHON namespace lldb { - class SBTypeSummaryOptions + class LLDB_API SBTypeSummaryOptions { public: SBTypeSummaryOptions(); diff --git a/include/lldb/API/SBTypeSynthetic.h b/include/lldb/API/SBTypeSynthetic.h index e77cbfef598c..5dd11757ba40 100644 --- a/include/lldb/API/SBTypeSynthetic.h +++ b/include/lldb/API/SBTypeSynthetic.h @@ -16,7 +16,7 @@ namespace lldb { - class SBTypeSynthetic + class LLDB_API SBTypeSynthetic { public: diff --git a/include/lldb/API/SBUnixSignals.h b/include/lldb/API/SBUnixSignals.h index 40bbed8b48ef..9eae30739bb8 100644 --- a/include/lldb/API/SBUnixSignals.h +++ b/include/lldb/API/SBUnixSignals.h @@ -14,7 +14,7 @@ namespace lldb { -class SBUnixSignals { +class LLDB_API SBUnixSignals { public: SBUnixSignals (); diff --git a/include/lldb/API/SBValue.h b/include/lldb/API/SBValue.h index bedac4ef1d2d..a070b149f34f 100644 --- a/include/lldb/API/SBValue.h +++ b/include/lldb/API/SBValue.h @@ -19,10 +19,8 @@ class ValueLocker; namespace lldb { -class SBValue +class LLDB_API SBValue { -friend class ValueLocker; - public: SBValue (); @@ -84,6 +82,7 @@ friend class ValueLocker; ValueType GetValueType (); + // If you call this on a newly created ValueObject, it will always return false. bool GetValueDidChange (); @@ -223,7 +222,7 @@ friend class ValueLocker; /// and also if the target can be run to figure out the dynamic /// type of the child value. /// - /// @param[in] synthetic_allowed + /// @param[in] can_create_synthetic /// If \b true, then allow child values to be created by index /// for pointers and arrays for indexes that normally wouldn't /// be allowed. @@ -326,6 +325,9 @@ friend class ValueLocker; //------------------------------------------------------------------ bool MightHaveChildren (); + + bool + IsRuntimeSupportValue (); uint32_t GetNumChildren (); @@ -386,7 +388,7 @@ friend class ValueLocker; /// @param[in] write /// Stop when this value is modified /// - /// @param[out] + /// @param[out] error /// An error object. Contains the reason if there is some failure. /// /// @return @@ -419,7 +421,7 @@ friend class ValueLocker; /// @param[in] write /// Stop when this value is modified /// - /// @param[out] + /// @param[out] error /// An error object. Contains the reason if there is some failure. /// /// @return diff --git a/include/lldb/API/SBValueList.h b/include/lldb/API/SBValueList.h index 812fdac91c11..563ca3d7e1bf 100644 --- a/include/lldb/API/SBValueList.h +++ b/include/lldb/API/SBValueList.h @@ -16,7 +16,7 @@ class ValueListImpl; namespace lldb { -class SBValueList +class LLDB_API SBValueList { public: diff --git a/include/lldb/API/SBVariablesOptions.h b/include/lldb/API/SBVariablesOptions.h new file mode 100644 index 000000000000..527310f5dfc7 --- /dev/null +++ b/include/lldb/API/SBVariablesOptions.h @@ -0,0 +1,98 @@ +//===-- SBVariablesOptions.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBVariablesOptions_h_ +#define LLDB_SBVariablesOptions_h_ + +#include "lldb/API/SBDefines.h" + +class VariablesOptionsImpl; + +namespace lldb { + +class LLDB_API SBVariablesOptions +{ +public: + SBVariablesOptions (); + + SBVariablesOptions (const SBVariablesOptions& options); + + SBVariablesOptions& + operator = (const SBVariablesOptions& options); + + ~SBVariablesOptions (); + + bool + IsValid () const; + + bool + GetIncludeArguments () const; + + void + SetIncludeArguments (bool); + + bool + GetIncludeLocals () const; + + void + SetIncludeLocals (bool); + + bool + GetIncludeStatics () const; + + void + SetIncludeStatics (bool); + + bool + GetInScopeOnly () const; + + void + SetInScopeOnly (bool); + + bool + GetIncludeRuntimeSupportValues () const; + + void + SetIncludeRuntimeSupportValues (bool); + + lldb::DynamicValueType + GetUseDynamic () const; + + void + SetUseDynamic (lldb::DynamicValueType); + +protected: + VariablesOptionsImpl * + operator->(); + + const VariablesOptionsImpl * + operator->() const; + + VariablesOptionsImpl * + get (); + + VariablesOptionsImpl & + ref(); + + const VariablesOptionsImpl & + ref() const; + + SBVariablesOptions (VariablesOptionsImpl *lldb_object_ptr); + + void + SetOptions (VariablesOptionsImpl *lldb_object_ptr); + +private: + + std::unique_ptr m_opaque_ap; +}; + +} // namespace lldb + +#endif // LLDB_SBValue_h_ diff --git a/include/lldb/API/SBWatchpoint.h b/include/lldb/API/SBWatchpoint.h index 9bf51fd1ad05..5d0d48ee12f2 100644 --- a/include/lldb/API/SBWatchpoint.h +++ b/include/lldb/API/SBWatchpoint.h @@ -14,7 +14,7 @@ namespace lldb { -class SBWatchpoint +class LLDB_API SBWatchpoint { public: diff --git a/include/lldb/API/SystemInitializerFull.h b/include/lldb/API/SystemInitializerFull.h new file mode 100644 index 000000000000..6280fe8aef04 --- /dev/null +++ b/include/lldb/API/SystemInitializerFull.h @@ -0,0 +1,40 @@ +//===-- SystemInitializerFull.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_API_SYSTEM_INITIALIZER_FULL_H +#define LLDB_API_SYSTEM_INITIALIZER_FULL_H + +#include "lldb/Initialization/SystemInitializerCommon.h" + +namespace lldb_private +{ +//------------------------------------------------------------------ +/// Initializes lldb. +/// +/// This class is responsible for initializing all of lldb system +/// services needed to use the full LLDB application. This class is +/// not intended to be used externally, but is instead used +/// internally by SBDebugger to initialize the system. +//------------------------------------------------------------------ +class SystemInitializerFull : public SystemInitializerCommon +{ + public: + SystemInitializerFull(); + virtual ~SystemInitializerFull(); + + void Initialize() override; + void Terminate() override; + + private: + void InitializeSWIG(); + void TerminateSWIG(); +}; +} + +#endif diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h index 883571a3ce9a..a70c2787a1ef 100644 --- a/include/lldb/Breakpoint/Breakpoint.h +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -155,6 +155,23 @@ class Breakpoint: }; + class BreakpointPrecondition + { + public: + virtual ~BreakpointPrecondition() {} + + virtual bool + EvaluatePrecondition(StoppointCallbackContext &context); + + virtual Error + ConfigurePrecondition(Args &options); + + virtual void + DescribePrecondition(Stream &stream, lldb::DescriptionLevel level); + }; + + typedef std::shared_ptr BreakpointPreconditionSP; + //------------------------------------------------------------------ /// Destructor. /// @@ -665,6 +682,31 @@ class Breakpoint: } } + //------------------------------------------------------------------ + /// Set a pre-condition filter that overrides all user provided filters/callbacks etc. + /// + /// Used to define fancy breakpoints that can do dynamic hit detection without taking up the condition slot - + /// which really belongs to the user anyway... + /// + /// The Precondition should not continue the target, it should return true if the condition says to stop and + /// false otherwise. + /// + //------------------------------------------------------------------ + void + SetPrecondition(BreakpointPreconditionSP precondition_sp) + { + m_precondition_sp = precondition_sp; + } + + bool + EvaluatePrecondition (StoppointCallbackContext &context); + + BreakpointPreconditionSP + GetPrecondition() + { + return m_precondition_sp; + } + protected: friend class Target; //------------------------------------------------------------------ @@ -737,13 +779,17 @@ class Breakpoint: // For Breakpoint only //------------------------------------------------------------------ bool m_being_created; - bool m_hardware; // If this breakpoint is required to use a hardware breakpoint - Target &m_target; // The target that holds this breakpoint. + bool m_hardware; // If this breakpoint is required to use a hardware breakpoint + Target &m_target; // The target that holds this breakpoint. std::unordered_set m_name_list; // If not empty, this is the name of this breakpoint (many breakpoints can share the same name.) - lldb::SearchFilterSP m_filter_sp; // The filter that constrains the breakpoint's domain. - lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint. - BreakpointOptions m_options; // Settable breakpoint options - BreakpointLocationList m_locations; // The list of locations currently found for this breakpoint. + lldb::SearchFilterSP m_filter_sp; // The filter that constrains the breakpoint's domain. + lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint. + BreakpointPreconditionSP m_precondition_sp; // The precondition is a breakpoint-level hit filter that can be used + // to skip certain breakpoint hits. For instance, exception breakpoints + // use this to limit the stop to certain exception classes, while leaving + // the condition & callback free for user specification. + BreakpointOptions m_options; // Settable breakpoint options + BreakpointLocationList m_locations; // The list of locations currently found for this breakpoint. std::string m_kind_description; bool m_resolve_indirect_symbols; uint32_t m_hit_count; // Number of times this breakpoint/watchpoint has been hit. This is kept diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h index 642256386785..c3e620d085c6 100644 --- a/include/lldb/Breakpoint/BreakpointLocation.h +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -21,11 +21,8 @@ #include "lldb/lldb-private.h" #include "lldb/Breakpoint/StoppointLocation.h" #include "lldb/Core/Address.h" -#include "lldb/Core/StringList.h" #include "lldb/Core/UserID.h" #include "lldb/Host/Mutex.h" -#include "lldb/Target/Process.h" -#include "lldb/Expression/ClangUserExpression.h" namespace lldb_private { @@ -464,7 +461,7 @@ class BreakpointLocation : Breakpoint &m_owner; ///< The breakpoint that produced this object. std::unique_ptr m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options. lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.) - ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition. + lldb::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition. Mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by multiple processes. size_t m_condition_hash; ///< For testing whether the condition source code changed. diff --git a/include/lldb/Breakpoint/BreakpointOptions.h b/include/lldb/Breakpoint/BreakpointOptions.h index eb374ad69603..bf10fc096d75 100644 --- a/include/lldb/Breakpoint/BreakpointOptions.h +++ b/include/lldb/Breakpoint/BreakpointOptions.h @@ -89,6 +89,9 @@ class BreakpointOptions // callback. // Asynchronous callbacks get run as part of the "ShouldStop" logic in the thread plan. The logic there is: // a) If the breakpoint is thread specific and not for this thread, continue w/o running the callback. + // NB. This is actually enforced underneath the breakpoint system, the Process plugin is expected to + // call BreakpointSite::IsValidForThread, and set the thread's StopInfo to "no reason". That way, + // thread displays won't show stops for breakpoints not for that thread... // b) If the ignore count says we shouldn't stop, then ditto. // c) If the condition says we shouldn't stop, then ditto. // d) Otherwise, the callback will get run, and if it returns true we will stop, and if false we won't. diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h index cd62bcd032b0..2403d24515a7 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -32,7 +32,8 @@ class BreakpointResolverFileLine : const FileSpec &resolver, uint32_t line_no, bool check_inlines, - bool skip_prologue); + bool skip_prologue, + bool exact_match); virtual ~BreakpointResolverFileLine (); @@ -67,6 +68,7 @@ class BreakpointResolverFileLine : uint32_t m_line_number; // This is the line number that we are looking for. bool m_inlines; // This determines whether the resolver looks for inlined functions or not. bool m_skip_prologue; + bool m_exact_match; private: DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileLine); diff --git a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h index 2c05ac1c87da..8e18fff16447 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -29,7 +29,8 @@ class BreakpointResolverFileRegex : { public: BreakpointResolverFileRegex (Breakpoint *bkpt, - RegularExpression ®ex); + RegularExpression ®ex, + bool exact_match); virtual ~BreakpointResolverFileRegex (); @@ -61,6 +62,7 @@ class BreakpointResolverFileRegex : protected: friend class Breakpoint; RegularExpression m_regex; // This is the line expression that we are looking for. + bool m_exact_match; private: DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex); diff --git a/include/lldb/Breakpoint/BreakpointSite.h b/include/lldb/Breakpoint/BreakpointSite.h index c6dbef781f22..d67fc8bb57f1 100644 --- a/include/lldb/Breakpoint/BreakpointSite.h +++ b/include/lldb/Breakpoint/BreakpointSite.h @@ -18,7 +18,7 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" +#include "lldb/lldb-forward.h" #include "lldb/Host/Mutex.h" #include "lldb/Core/UserID.h" #include "lldb/Breakpoint/StoppointLocation.h" diff --git a/include/lldb/Breakpoint/Watchpoint.h b/include/lldb/Breakpoint/Watchpoint.h index 8493775eec34..926e0b506f31 100644 --- a/include/lldb/Breakpoint/Watchpoint.h +++ b/include/lldb/Breakpoint/Watchpoint.h @@ -20,10 +20,11 @@ // Project includes #include "lldb/lldb-private.h" -#include "lldb/Target/Target.h" -#include "lldb/Core/UserID.h" #include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Breakpoint/StoppointLocation.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Target/Target.h" namespace lldb_private { @@ -205,7 +206,18 @@ class Watchpoint : friend class Target; friend class WatchpointList; - void ResetHitCount() { m_hit_count = 0; } + void + ResetHitCount () + { + m_hit_count = 0; + } + + void + ResetHistoricValues () + { + m_old_value_sp.reset(nullptr); + m_new_value_sp.reset(nullptr); + } Target &m_target; bool m_enabled; // Is this watchpoint enabled diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h index b430ef7cec21..cfa16c30bedb 100644 --- a/include/lldb/Core/Address.h +++ b/include/lldb/Core/Address.h @@ -88,6 +88,8 @@ class Address ///< if the address is in a section (section of pointers, c strings, etc). DumpStyleResolvedDescriptionNoModule, DumpStyleResolvedDescriptionNoFunctionArguments, + DumpStyleNoFunctionName, ///< Elide the function name; display an offset into the current function. + ///< Used primarily in disassembly symbolication DumpStyleDetailedSymbolContext, ///< Detailed symbol context information for an address for all symbol ///< context members. DumpStyleResolvedPointerDescription ///< Dereference a pointer at the current address and then lookup the diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 93630f043822..0cadd8d8dec6 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -12,9 +12,8 @@ #if defined(__cplusplus) -#include "lldb/lldb-private.h" +#include "lldb/lldb-forward.h" #include "lldb/Core/ConstString.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" namespace lldb_private { @@ -33,6 +32,23 @@ struct CoreDefinition; class ArchSpec { public: + enum MIPSSubType + { + eMIPSSubType_unknown, + eMIPSSubType_mips32, + eMIPSSubType_mips32r2, + eMIPSSubType_mips32r6, + eMIPSSubType_mips32el, + eMIPSSubType_mips32r2el, + eMIPSSubType_mips32r6el, + eMIPSSubType_mips64, + eMIPSSubType_mips64r2, + eMIPSSubType_mips64r6, + eMIPSSubType_mips64el, + eMIPSSubType_mips64r2el, + eMIPSSubType_mips64r6el, + }; + enum Core { eCore_arm_generic, @@ -66,8 +82,27 @@ class ArchSpec eCore_arm_arm64, eCore_arm_armv8, eCore_arm_aarch64, - + + eCore_mips32, + eCore_mips32r2, + eCore_mips32r3, + eCore_mips32r5, + eCore_mips32r6, + eCore_mips32el, + eCore_mips32r2el, + eCore_mips32r3el, + eCore_mips32r5el, + eCore_mips32r6el, eCore_mips64, + eCore_mips64r2, + eCore_mips64r3, + eCore_mips64r5, + eCore_mips64r6, + eCore_mips64el, + eCore_mips64r2el, + eCore_mips64r3el, + eCore_mips64r5el, + eCore_mips64r6el, eCore_ppc_generic, eCore_ppc_ppc601, @@ -142,7 +177,19 @@ class ArchSpec kCore_hexagon_last = eCore_hexagon_hexagonv5, kCore_kalimba_first = eCore_kalimba3, - kCore_kalimba_last = eCore_kalimba5 + kCore_kalimba_last = eCore_kalimba5, + + kCore_mips32_first = eCore_mips32, + kCore_mips32_last = eCore_mips32r6, + + kCore_mips32el_first = eCore_mips32el, + kCore_mips32el_last = eCore_mips32r6el, + + kCore_mips64_first = eCore_mips64, + kCore_mips64_last = eCore_mips64r6, + + kCore_mips64el_first = eCore_mips64el, + kCore_mips64el_last = eCore_mips64r6el }; typedef void (* StopInfoOverrideCallbackType)(lldb_private::Thread &thread); @@ -290,58 +337,48 @@ class ArchSpec //------------------------------------------------------------------ void MergeFrom(const ArchSpec &other); - - //------------------------------------------------------------------ - /// Sets this ArchSpec according to the given architecture name. - /// - /// The architecture name can be one of the generic system default - /// values: - /// - /// @li \c LLDB_ARCH_DEFAULT - The arch the current system defaults - /// to when a program is launched without any extra - /// attributes or settings. - /// @li \c LLDB_ARCH_DEFAULT_32BIT - The default host architecture - /// for 32 bit (if any). - /// @li \c LLDB_ARCH_DEFAULT_64BIT - The default host architecture - /// for 64 bit (if any). - /// - /// Alternatively, if the object type of this ArchSpec has been - /// configured, a concrete architecture can be specified to set - /// the CPU type ("x86_64" for example). - /// - /// Finally, an encoded object and archetecture format is accepted. - /// The format contains an object type (like "macho" or "elf"), - /// followed by a platform dependent encoding of CPU type and - /// subtype. For example: - /// - /// "macho" : Specifies an object type of MachO. - /// "macho-16-6" : MachO specific encoding for ARMv6. - /// "elf-43 : ELF specific encoding for Sparc V9. - /// - /// @param[in] arch_name The name of an architecture. - /// - /// @return True if @p arch_name was successfully translated, false - /// otherwise. - //------------------------------------------------------------------ -// bool -// SetArchitecture (const llvm::StringRef& arch_name); -// -// bool -// SetArchitecture (const char *arch_name); //------------------------------------------------------------------ - /// Change the architecture object type and CPU type. + /// Change the architecture object type, CPU type and OS type. /// /// @param[in] arch_type The object type of this ArchSpec. /// /// @param[in] cpu The required CPU type. /// - /// @return True if the object and CPU type were successfully set. + /// @param[in] os The optional OS type + /// The default value of 0 was choosen to from the ELF spec value + /// ELFOSABI_NONE. ELF is the only one using this parameter. If another + /// format uses this parameter and 0 does not work, use a value over + /// 255 because in the ELF header this is value is only a byte. + /// + /// @return True if the object, and CPU were successfully set. + /// + /// As a side effect, the vendor value is usually set to unknown. + /// The exections are + /// aarch64-apple-ios + /// arm-apple-ios + /// thumb-apple-ios + /// x86-apple- + /// x86_64-apple- + /// + /// As a side effect, the os value is usually set to unknown + /// The exceptions are + /// *-*-aix + /// aarch64-apple-ios + /// arm-apple-ios + /// thumb-apple-ios + /// powerpc-apple-darwin + /// *-*-freebsd + /// *-*-linux + /// *-*-netbsd + /// *-*-openbsd + /// *-*-solaris //------------------------------------------------------------------ bool SetArchitecture (ArchitectureType arch_type, uint32_t cpu, - uint32_t sub); + uint32_t sub, + uint32_t os = 0); //------------------------------------------------------------------ /// Returns the byte order for the architecture specification. @@ -456,8 +493,18 @@ class ArchSpec GetDefaultEndian () const; //------------------------------------------------------------------ - /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu - /// type match between them. + /// Returns true if 'char' is a signed type by defualt in the + /// architecture false otherwise + /// + /// @return True if 'char' is a signed type by default on the + /// architecture and false otherwise. + //------------------------------------------------------------------ + bool + CharIsSignedByDefault () const; + + //------------------------------------------------------------------ + /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu + /// type match between them. /// e.g. armv7s is not an exact match with armv7 - this would return false /// /// @return true if the two ArchSpecs match. diff --git a/include/lldb/Core/ClangForward.h b/include/lldb/Core/ClangForward.h index ef7308d25f7f..6c627c2ad3b7 100644 --- a/include/lldb/Core/ClangForward.h +++ b/include/lldb/Core/ClangForward.h @@ -72,11 +72,14 @@ namespace clang class FunctionTemplateSpecializationInfo; class GotoStmt; class HeaderSearchOptions; + class IdentifierInfo; class IdentifierTable; class IntegerLiteral; class LabelStmt; class LangOptions; + class MacroDirective; class MemberExpr; + class Module; class NamedDecl; class NamespaceDecl; class NonTypeTemplateParmDecl; diff --git a/include/lldb/Core/Communication.h b/include/lldb/Core/Communication.h index 49532fe123c5..7924ed293d3c 100644 --- a/include/lldb/Core/Communication.h +++ b/include/lldb/Core/Communication.h @@ -85,14 +85,16 @@ namespace lldb_private { class Communication : public Broadcaster { public: - enum { - eBroadcastBitDisconnected = (1 << 0), ///< Sent when the communications connection is lost. - eBroadcastBitReadThreadGotBytes = (1 << 1), ///< Sent by the read thread when bytes become available. - eBroadcastBitReadThreadDidExit = (1 << 2), ///< Sent by the read thread when it exits to inform clients. - eBroadcastBitReadThreadShouldExit = (1 << 3), ///< Sent by clients that need to cancel the read thread. - eBroadcastBitPacketAvailable = (1 << 4), ///< Sent when data received makes a complete packet. - kLoUserBroadcastBit = (1 << 16),///< Subclasses can used bits 31:16 for any needed events. - kHiUserBroadcastBit = (1 << 31), + 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 }; @@ -321,6 +323,16 @@ class Communication : public Broadcaster 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 const char * ConnectionStatusAsCString (lldb::ConnectionStatus status); @@ -354,9 +366,11 @@ class Communication : public Broadcaster 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. Mutex m_bytes_mutex; ///< A mutex to protect multi-threaded access to the cached bytes. Mutex m_write_mutex; ///< Don't let multiple threads write at the same time... + Mutex m_synchronize_mutex; ReadThreadBytesReceived m_callback; void *m_callback_baton; bool m_close_on_eof; diff --git a/include/lldb/Core/Connection.h b/include/lldb/Core/Connection.h index a7b911ac382f..c354519a222e 100644 --- a/include/lldb/Core/Connection.h +++ b/include/lldb/Core/Connection.h @@ -111,6 +111,13 @@ class Connection /// 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_usec + /// The number of microseconds to wait for the data. + /// + /// @param[out] status + /// On return, indicates whether the call was sucessful or terminated + /// due to some error condition. + /// /// @param[out] error_ptr /// A pointer to an error object that should be given an /// approriate error value if this method returns zero. This @@ -164,6 +171,22 @@ class Connection virtual std::string GetURI() = 0; + //------------------------------------------------------------------ + /// Interrupts an ongoing Read() operation. + /// + /// If there is an ongoing read operation in another thread, this operation + /// return with status == eConnectionStatusInterrupted. Note that if there + /// data waiting to be read and an interrupt request is issued, the Read() + /// function will return the data immediately without processing the + /// interrupt request (which will remain queued for the next Read() + /// operation). + /// + /// @return + /// Returns true is the interrupt request was sucessful. + //------------------------------------------------------------------ + virtual bool + InterruptRead() = 0; + private: //------------------------------------------------------------------ // For Connection only diff --git a/include/lldb/Core/ConstString.h b/include/lldb/Core/ConstString.h index cfa237c46862..cfe8ea2db0e1 100644 --- a/include/lldb/Core/ConstString.h +++ b/include/lldb/Core/ConstString.h @@ -233,7 +233,7 @@ class ConstString const char * AsCString(const char *value_if_empty = NULL) const { - if (m_string == NULL) + if (IsEmpty()) return value_if_empty; return m_string; } diff --git a/include/lldb/Core/CxaDemangle.h b/include/lldb/Core/CxaDemangle.h new file mode 100644 index 000000000000..0cd54fb36a32 --- /dev/null +++ b/include/lldb/Core/CxaDemangle.h @@ -0,0 +1,21 @@ +//===-- CxaDemangle.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CxaDemangle_h_ +#define liblldb_CxaDemangle_h_ + +namespace lldb_private +{ + + char* + __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status); + +} + +#endif diff --git a/include/lldb/Core/DataEncoder.h b/include/lldb/Core/DataEncoder.h index 7cd5d6808152..7889f4191e50 100644 --- a/include/lldb/Core/DataEncoder.h +++ b/include/lldb/Core/DataEncoder.h @@ -357,7 +357,7 @@ class DataEncoder /// The number of bytes that this object now contains. //------------------------------------------------------------------ uint32_t - SetData (const void *bytes, uint32_t length, lldb::ByteOrder byte_order); + SetData (void *bytes, uint32_t length, lldb::ByteOrder byte_order); //------------------------------------------------------------------ /// Adopt a subset of shared data in \a data_sp. @@ -446,7 +446,7 @@ class DataEncoder uint8_t *m_end; ///< A pointer to the byte that is past the end of the data. lldb::ByteOrder m_byte_order; ///< The byte order of the data we are extracting from. uint8_t m_addr_size; ///< The address size to use when extracting pointers or addresses - mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multilple instances + mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multiple instances private: DISALLOW_COPY_AND_ASSIGN (DataEncoder); diff --git a/include/lldb/Core/DataExtractor.h b/include/lldb/Core/DataExtractor.h index 516953b00c33..e61189b98103 100644 --- a/include/lldb/Core/DataExtractor.h +++ b/include/lldb/Core/DataExtractor.h @@ -234,7 +234,7 @@ class DataExtractor /// bytes into the contained data, into the stream \a s. \a /// num_per_line objects will be dumped on each line before a new /// line will be output. If \a base_addr is a valid address, then - /// each new line of output will be prededed by the address value + /// each new line of output will be preceded by the address value /// plus appropriate offset, and a colon and space. Bitfield values /// can be dumped by calling this function multiple times with the /// same start offset, format and size, yet differing \a @@ -574,7 +574,7 @@ class DataExtractor GetSharedDataOffset () const; //------------------------------------------------------------------ - /// Get a the data start pointer. + /// Get the data start pointer. /// /// @return /// Returns a pointer to the first byte contained in this @@ -908,7 +908,7 @@ class DataExtractor /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherise. + /// NULL otherwise. //------------------------------------------------------------------ void * GetU8 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -955,7 +955,7 @@ class DataExtractor /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherise. + /// NULL otherwise. //------------------------------------------------------------------ void * GetU16 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -1002,7 +1002,7 @@ class DataExtractor /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherise. + /// NULL otherwise. //------------------------------------------------------------------ void * GetU32 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -1049,7 +1049,7 @@ class DataExtractor /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherise. + /// NULL otherwise. //------------------------------------------------------------------ void * GetU64 ( lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -1328,7 +1328,7 @@ class DataExtractor const uint8_t * m_end; ///< A pointer to the byte that is past the end of the data. lldb::ByteOrder m_byte_order; ///< The byte order of the data we are extracting from. uint32_t m_addr_size; ///< The address size to use when extracting pointers or addresses - mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multilple instances + mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multiple instances const uint32_t m_target_byte_size; }; diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h index 9a3f9736fdca..0d9b90c8919d 100644 --- a/include/lldb/Core/Debugger.h +++ b/include/lldb/Core/Debugger.h @@ -14,22 +14,16 @@ #include -#include - #include "lldb/lldb-public.h" #include "lldb/Core/Broadcaster.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/Listener.h" #include "lldb/Core/SourceManager.h" #include "lldb/Core/UserID.h" #include "lldb/Core/UserSettingsController.h" -#include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/Terminal.h" -#include "lldb/Interpreter/OptionValueProperties.h" -#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "lldb/Target/TargetList.h" @@ -61,10 +55,6 @@ friend class SourceManager; // For GetSourceFileCache. public: - typedef llvm::sys::DynamicLibrary (*LoadPluginCallbackType) (const lldb::DebuggerSP &debugger_sp, - const FileSpec& spec, - Error& error); - static lldb::DebuggerSP CreateInstance (lldb::LogOutputCallback log_callback = NULL, void *baton = NULL); @@ -75,10 +65,10 @@ friend class SourceManager; // For GetSourceFileCache. FindTargetWithProcess (Process *process); static void - Initialize (LoadPluginCallbackType load_plugin_callback); + Initialize(LoadPluginCallbackType load_plugin_callback); - static void - Terminate (); + static void + Terminate(); static void SettingsInitialize (); @@ -220,6 +210,9 @@ friend class SourceManager; // For GetSourceFileCache. bool IsTopIOHandler (const lldb::IOHandlerSP& reader_sp); + void + PrintAsync (const char *s, size_t len, bool is_stdout); + ConstString GetTopIOHandlerControlSequence(char ch); @@ -229,12 +222,6 @@ friend class SourceManager; // For GetSourceFileCache. const char * GetIOHandlerHelpPrologue(); - bool - HideTopIOHandler(); - - void - RefreshTopIOHandler(); - static lldb::DebuggerSP FindDebuggerWithID (lldb::user_id_t id); @@ -258,9 +245,6 @@ friend class SourceManager; // For GetSourceFileCache. void ClearIOHandlers (); - static int - TestDebuggerRefCount (); - bool GetCloseInputOnEOF () const; @@ -360,7 +344,7 @@ friend class SourceManager; // For GetSourceFileCache. LoadPlugin (const FileSpec& spec, Error& error); void - ExecuteIOHanders(); + ExecuteIOHandlers(); bool IsForwardingEvents (); diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h index 64d35e67bfd0..e08e2def4c18 100644 --- a/include/lldb/Core/Disassembler.h +++ b/include/lldb/Core/Disassembler.h @@ -120,6 +120,12 @@ class Instruction /// @param[in] disassembly_addr_format /// The format specification for how addresses are printed. /// Only needed if show_address is true. + /// + /// @param[in] max_address_text_size + /// The length of the longest address string at the start of the + /// disassembly line that will be printed (the Debugger::FormatDisassemblerAddress() string) + /// so this method can properly align the instruction opcodes. + /// May be 0 to indicate no indentation/alignment of the opcodes. //------------------------------------------------------------------ virtual void @@ -130,7 +136,8 @@ class Instruction const ExecutionContext* exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, - const FormatEntity::Entry *disassembly_addr_format); + const FormatEntity::Entry *disassembly_addr_format, + size_t max_address_text_size); virtual bool DoesBranch () = 0; @@ -218,7 +225,7 @@ class InstructionList GetInstructionAtIndex (size_t idx) const; uint32_t - GetIndexOfNextBranchInstruction(uint32_t start) const; + GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const; uint32_t GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target); diff --git a/include/lldb/Core/FastDemangle.h b/include/lldb/Core/FastDemangle.h new file mode 100644 index 000000000000..cd6128c73038 --- /dev/null +++ b/include/lldb/Core/FastDemangle.h @@ -0,0 +1,24 @@ +//===-- FastDemangle.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_FastDemangle_h_ +#define liblldb_FastDemangle_h_ + +namespace lldb_private +{ + + char * + FastDemangle(const char *mangled_name); + + char * + FastDemangle(const char *mangled_name, long mangled_name_length); + +} + +#endif diff --git a/include/lldb/Core/FormatEntity.h b/include/lldb/Core/FormatEntity.h index 32ff9ea4e3eb..db4f59132832 100644 --- a/include/lldb/Core/FormatEntity.h +++ b/include/lldb/Core/FormatEntity.h @@ -61,6 +61,7 @@ namespace lldb_private ScriptTarget, ModuleFile, File, + Lang, FrameIndex, FrameRegisterPC, FrameRegisterSP, @@ -78,6 +79,8 @@ namespace lldb_private FunctionAddrOffsetConcrete, FunctionLineOffset, FunctionPCOffset, + FunctionInitial, + FunctionChanged, LineEntryFile, LineEntryLineNumber, LineEntryStartAddress, diff --git a/include/lldb/Core/IOHandler.h b/include/lldb/Core/IOHandler.h index 02e6bde1edb6..b617d8e75f58 100644 --- a/include/lldb/Core/IOHandler.h +++ b/include/lldb/Core/IOHandler.h @@ -67,18 +67,6 @@ namespace lldb_private { virtual void Run () = 0; - // Hide any characters that have been displayed so far so async - // output can be displayed. Refresh() will be called after the - // output has been displayed. - virtual void - Hide () = 0; - - // Called when the async output has been received in order to update - // the input reader (refresh the prompt and redisplay any current - // line(s) that are being edited - virtual void - Refresh () = 0; - // Called when an input reader should relinquish its control so another // can be pushed onto the IO handler stack, or so the current IO // handler can pop itself off the stack @@ -246,7 +234,14 @@ namespace lldb_private { void WaitForPop (); - + + virtual void + PrintAsync (Stream *stream, const char *s, size_t len) + { + stream->Write (s, len); + stream->Flush(); + } + protected: Debugger &m_debugger; lldb::StreamFileSP m_input_sp; @@ -318,7 +313,7 @@ namespace lldb_private { } //------------------------------------------------------------------ - /// Called when a new line is created or one of an identifed set of + /// Called when a new line is created or one of an identified set of /// indentation characters is typed. /// /// This function determines how much indentation should be added @@ -332,7 +327,7 @@ namespace lldb_private { /// following the line containing the cursor are not included. /// /// @param[in] cursor_position - /// The number of characters preceeding the cursor on the final + /// The number of characters preceding the cursor on the final /// line at the time. /// /// @return @@ -448,17 +443,17 @@ namespace lldb_private { { } - virtual ConstString - IOHandlerGetControlSequence (char ch) + ConstString + IOHandlerGetControlSequence (char ch) override { if (ch == 'd') return ConstString (m_end_line + "\n"); return ConstString(); } - virtual bool + bool IOHandlerIsInputComplete (IOHandler &io_handler, - StringList &lines) + StringList &lines) override { // Determine whether the end of input signal has been entered const size_t num_lines = lines.GetSize(); @@ -507,53 +502,47 @@ namespace lldb_private { virtual ~IOHandlerEditline (); - virtual void - Run (); + void + Run () override; - virtual void - Hide (); + void + Cancel () override; - virtual void - Refresh (); - - virtual void - Cancel (); - - virtual bool - Interrupt (); + bool + Interrupt () override; - virtual void - GotEOF(); + void + GotEOF() override; - virtual void - Activate (); + void + Activate () override; - virtual void - Deactivate (); + void + Deactivate () override; - virtual ConstString - GetControlSequence (char ch) + ConstString + GetControlSequence (char ch) override { return m_delegate.IOHandlerGetControlSequence (ch); } - virtual const char * - GetCommandPrefix () + const char * + GetCommandPrefix () override { return m_delegate.IOHandlerGetCommandPrefix (); } - virtual const char * - GetHelpPrologue () + const char * + GetHelpPrologue () override { return m_delegate.IOHandlerGetHelpPrologue (); } - virtual const char * - GetPrompt (); + const char * + GetPrompt () override; - virtual bool - SetPrompt (const char *prompt); + bool + SetPrompt (const char *prompt) override; const char * GetContinuationPrompt (); @@ -591,6 +580,9 @@ namespace lldb_private { uint32_t GetCurrentLineIndex () const; + void + PrintAsync (Stream *stream, const char *s, size_t len) override; + private: #ifndef LLDB_DISABLE_LIBEDIT static bool @@ -626,6 +618,7 @@ namespace lldb_private { 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) }; // The order of base classes is important. Look at the constructor of IOHandlerConfirm @@ -648,17 +641,17 @@ namespace lldb_private { return m_user_response; } - virtual int + int IOHandlerComplete (IOHandler &io_handler, const char *current_line, const char *cursor, const char *last_char, int skip_first_n_matches, int max_matches, - StringList &matches); + StringList &matches) override; - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data); + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override; protected: const bool m_default_response; @@ -671,32 +664,25 @@ namespace lldb_private { public: IOHandlerCursesGUI (Debugger &debugger); - virtual - ~IOHandlerCursesGUI (); + ~IOHandlerCursesGUI () override; - virtual void - Run (); + void + Run () override; - virtual void - Hide (); - - virtual void - Refresh (); + void + Cancel () override; - virtual void - Cancel (); - - virtual bool - Interrupt (); + bool + Interrupt () override; - virtual void - GotEOF(); + void + GotEOF() override; - virtual void - Activate (); + void + Activate () override; - virtual void - Deactivate (); + void + Deactivate () override; protected: curses::ApplicationAP m_app_ap; @@ -711,20 +697,11 @@ namespace lldb_private { virtual ~IOHandlerCursesValueObjectList (); - virtual void - Run (); + void + Run () override; - virtual void - Hide (); - - virtual void - Refresh (); - - virtual bool - HandleInterrupt (); - - virtual void - GotEOF(); + void + GotEOF() override; protected: ValueObjectList m_valobj_list; }; @@ -849,7 +826,10 @@ namespace lldb_private { return NULL; } - protected: + void + PrintAsync (Stream *stream, const char *s, size_t len); + + protected: typedef std::vector collection; collection m_stack; diff --git a/include/lldb/Core/Log.h b/include/lldb/Core/Log.h index b389946e264c..3aa4b4d48e17 100644 --- a/include/lldb/Core/Log.h +++ b/include/lldb/Core/Log.h @@ -22,19 +22,9 @@ #include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Flags.h" +#include "lldb/Core/Logging.h" #include "lldb/Core/PluginInterface.h" -//---------------------------------------------------------------------- -// Logging types -//---------------------------------------------------------------------- -#define LLDB_LOG_FLAG_STDOUT (1u << 0) -#define LLDB_LOG_FLAG_STDERR (1u << 1) -#define LLDB_LOG_FLAG_FATAL (1u << 2) -#define LLDB_LOG_FLAG_ERROR (1u << 3) -#define LLDB_LOG_FLAG_WARNING (1u << 4) -#define LLDB_LOG_FLAG_DEBUG (1u << 5) -#define LLDB_LOG_FLAG_VERBOSE (1u << 6) - //---------------------------------------------------------------------- // Logging Options //---------------------------------------------------------------------- @@ -46,6 +36,7 @@ #define LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD (1u << 5) #define LLDB_LOG_OPTION_PREPEND_THREAD_NAME (1U << 6) #define LLDB_LOG_OPTION_BACKTRACE (1U << 7) +#define LLDB_LOG_OPTION_APPEND (1U << 8) //---------------------------------------------------------------------- // Logging Functions @@ -59,12 +50,10 @@ class Log //------------------------------------------------------------------ // Callback definitions for abstracted plug-in log access. //------------------------------------------------------------------ - typedef void (*DisableCallback) (const char **categories, Stream *feedback_strm); - typedef Log * (*EnableCallback) (lldb::StreamSP &log_stream_sp, - uint32_t log_options, - const char **categories, - Stream *feedback_strm); - typedef void (*ListCategoriesCallback) (Stream *strm); + typedef void (*DisableCallback)(const char **categories, Stream *feedback_strm); + typedef Log *(*EnableCallback)(lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, + Stream *feedback_strm); + typedef void (*ListCategoriesCallback)(Stream *strm); struct Callbacks { @@ -77,86 +66,85 @@ class Log // Static accessors for logging channels //------------------------------------------------------------------ static void - RegisterLogChannel (const ConstString &channel, - const Log::Callbacks &log_callbacks); + RegisterLogChannel(const ConstString &channel, const Log::Callbacks &log_callbacks); static bool - UnregisterLogChannel (const ConstString &channel); + UnregisterLogChannel(const ConstString &channel); static bool - GetLogChannelCallbacks (const ConstString &channel, - Log::Callbacks &log_callbacks); + GetLogChannelCallbacks(const ConstString &channel, Log::Callbacks &log_callbacks); + static bool + EnableLogChannel(lldb::StreamSP &log_stream_sp, uint32_t log_options, const char *channel, + const char **categories, Stream &error_stream); static void - EnableAllLogChannels (lldb::StreamSP &log_stream_sp, - uint32_t log_options, - const char **categories, - Stream *feedback_strm); + EnableAllLogChannels(lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, + Stream *feedback_strm); static void - DisableAllLogChannels (Stream *feedback_strm); + DisableAllLogChannels(Stream *feedback_strm); static void - ListAllLogChannels (Stream *strm); + ListAllLogChannels(Stream *strm); static void - Initialize (); + Initialize(); static void - Terminate (); - + Terminate(); + //------------------------------------------------------------------ // Auto completion //------------------------------------------------------------------ static void - AutoCompleteChannelName (const char *channel_name, - StringList &matches); + AutoCompleteChannelName(const char *channel_name, StringList &matches); //------------------------------------------------------------------ // Member functions //------------------------------------------------------------------ - Log (); + Log(); - Log (const lldb::StreamSP &stream_sp); + Log(const lldb::StreamSP &stream_sp); - ~Log (); + virtual + ~Log(); - void - PutCString (const char *cstr); + virtual void + PutCString(const char *cstr); - void - Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + Printf(const char *format, ...) __attribute__((format(printf, 2, 3))); - void - VAPrintf (const char *format, va_list args); + virtual void + VAPrintf(const char *format, va_list args); - void - PrintfWithFlags( uint32_t flags, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + virtual void + LogIf(uint32_t mask, const char *fmt, ...) __attribute__((format(printf, 3, 4))); - void - LogIf (uint32_t mask, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); + virtual void + Debug(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - void - Debug (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + DebugVerbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - void - DebugVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + Error(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - void - Error (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + VAError(const char *format, va_list args); - void - FatalError (int err, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); + virtual void + FatalError(int err, const char *fmt, ...) __attribute__((format(printf, 3, 4))); - void - Verbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + Verbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - void - Warning (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + Warning(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - void - WarningVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + virtual void + WarningVerbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); Flags & GetOptions(); @@ -177,7 +165,7 @@ class Log GetDebug() const; void - SetStream (const lldb::StreamSP &stream_sp) + SetStream(const lldb::StreamSP &stream_sp) { m_stream_sp = stream_sp; } @@ -190,43 +178,35 @@ class Log Flags m_options; Flags m_mask_bits; - void - PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args); - private: - DISALLOW_COPY_AND_ASSIGN (Log); + DISALLOW_COPY_AND_ASSIGN(Log); }; class LogChannel : public PluginInterface { public: - LogChannel (); + LogChannel(); - virtual - ~LogChannel (); + virtual ~LogChannel(); - static lldb::LogChannelSP - FindPlugin (const char *plugin_name); + static lldb::LogChannelSP FindPlugin(const char *plugin_name); // categories is a an array of chars that ends with a NULL element. - virtual void - Disable (const char **categories, Stream *feedback_strm) = 0; + virtual void Disable(const char **categories, Stream *feedback_strm) = 0; - virtual bool - Enable (lldb::StreamSP &log_stream_sp, - uint32_t log_options, - Stream *feedback_strm, // Feedback stream for argument errors etc - const char **categories) = 0;// The categories to enable within this logging stream, if empty, enable default set + virtual bool Enable( + lldb::StreamSP &log_stream_sp, uint32_t log_options, + Stream *feedback_strm, // Feedback stream for argument errors etc + const char **categories) = 0; // The categories to enable within this logging stream, if empty, enable default set - virtual void - ListCategories (Stream *strm) = 0; + virtual void ListCategories(Stream *strm) = 0; protected: std::unique_ptr m_log_ap; private: - DISALLOW_COPY_AND_ASSIGN (LogChannel); + DISALLOW_COPY_AND_ASSIGN(LogChannel); }; diff --git a/include/lldb/lldb-private-log.h b/include/lldb/Core/Logging.h similarity index 94% rename from include/lldb/lldb-private-log.h rename to include/lldb/Core/Logging.h index dc37ae2c7c42..a4dd76f11237 100644 --- a/include/lldb/lldb-private-log.h +++ b/include/lldb/Core/Logging.h @@ -1,4 +1,4 @@ -//===-- lldb-private-log.h --------------------------------------*- C++ -*-===// +//===-- Logging.h -----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_lldb_private_log_h_ -#define liblldb_lldb_private_log_h_ +#ifndef liblldb_Core_Logging_h_ +#define liblldb_Core_Logging_h_ // C Includes // C++ Includes @@ -47,6 +47,7 @@ #define LIBLLDB_LOG_PLATFORM (1u << 25) #define LIBLLDB_LOG_SYSTEM_RUNTIME (1u << 26) #define LIBLLDB_LOG_JIT_LOADER (1u << 27) +#define LIBLLDB_LOG_LANGUAGE (1u << 28) #define LIBLLDB_LOG_ALL (UINT32_MAX) #define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\ LIBLLDB_LOG_THREAD |\ @@ -90,4 +91,4 @@ ListLogCategories (Stream *strm); } // namespace lldb_private -#endif // liblldb_lldb_private_log_h_ +#endif // liblldb_Core_Logging_h_ diff --git a/include/lldb/Core/Mangled.h b/include/lldb/Core/Mangled.h index 87b23799882f..a2a2b5591d0f 100644 --- a/include/lldb/Core/Mangled.h +++ b/include/lldb/Core/Mangled.h @@ -41,6 +41,13 @@ class Mangled ePreferDemangledWithoutArguments }; + enum ManglingScheme + { + eManglingSchemeNone = 0, + eManglingSchemeMSVC, + eManglingSchemeItanium + }; + //---------------------------------------------------------------------- /// Default constructor. /// @@ -291,12 +298,12 @@ class Mangled SetValue (const ConstString &name); //---------------------------------------------------------------------- - /// Get the language only if it is definitive what the language is from - /// the mangling. + /// Try to guess the language from the mangling. /// /// For a mangled name to have a language it must have both a mangled - /// and a demangled name and it must be definitive from the mangling - /// what the language is. + /// and a demangled name and it can be guessed from the mangling what + /// the language is. Note: this will return C++ for any language that + /// uses Itanium ABI mangling. /// /// Standard C function names will return eLanguageTypeUnknown because /// they aren't mangled and it isn't clear what language the name @@ -307,7 +314,7 @@ class Mangled /// if there is no mangled or demangled counterpart. //---------------------------------------------------------------------- lldb::LanguageType - GetLanguage (); + GuessLanguage () const; private: //---------------------------------------------------------------------- diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h index 60fbb989502e..127ddaeb9fd4 100644 --- a/include/lldb/Core/Module.h +++ b/include/lldb/Core/Module.h @@ -10,12 +10,12 @@ #ifndef liblldb_Module_h_ #define liblldb_Module_h_ +#include "lldb/lldb-forward.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/UUID.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/TimeValue.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Target/PathMappingList.h" @@ -1098,7 +1098,7 @@ class Module : mutable Mutex m_mutex; ///< A mutex to keep this object happy in multi-threaded environments. TimeValue m_mod_time; ///< The modification time for this module when it was created. ArchSpec m_arch; ///< The architecture for this module. - lldb_private::UUID m_uuid; ///< Each module is assumed to have a unique identifier to help match it up to debug symbols. + UUID m_uuid; ///< Each module is assumed to have a unique identifier to help match it up to debug symbols. FileSpec m_file; ///< The file representation on disk for this module (if there is one). FileSpec m_platform_file;///< The path to the module on the platform on which it is being debugged FileSpec m_remote_install_file; ///< If set when debugging on remote platforms, this module will be installed at this location @@ -1107,10 +1107,12 @@ class Module : uint64_t m_object_offset; TimeValue m_object_mod_time; 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 - std::unique_ptr m_symfile_ap; ///< A pointer to the symbol vendor for this module. - ClangASTContext m_ast; ///< The AST context for this module. + lldb::SymbolVendorUP m_symfile_ap; ///< A pointer to the symbol vendor for this module. + std::vector m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and changes the symbol file, + ///< we need to keep all old symbol files around in case anyone has type references to them + lldb::ClangASTContextUP m_ast; ///< The AST context for this module. PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are - std::unique_ptr m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info + lldb::SectionListUP m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info bool m_did_load_objfile:1, m_did_load_symbol_vendor:1, diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h index a46e212da9bb..f4c12cf168ac 100644 --- a/include/lldb/Core/ModuleList.h +++ b/include/lldb/Core/ModuleList.h @@ -12,6 +12,7 @@ #include #include +#include #include "lldb/lldb-private.h" #include "lldb/Host/Mutex.h" @@ -562,6 +563,9 @@ class ModuleList static bool RemoveSharedModuleIfOrphaned (const Module *module_ptr); + void + ForEach (std::function const &callback) const; + protected: //------------------------------------------------------------------ // Class typedefs. diff --git a/include/lldb/Core/ModuleSpec.h b/include/lldb/Core/ModuleSpec.h index 195fd991f8de..be7041981a0a 100644 --- a/include/lldb/Core/ModuleSpec.h +++ b/include/lldb/Core/ModuleSpec.h @@ -14,6 +14,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/UUID.h" #include "lldb/Host/FileSpec.h" +#include "lldb/Host/Mutex.h" #include "lldb/Target/PathMappingList.h" namespace lldb_private { @@ -29,6 +30,7 @@ class ModuleSpec m_uuid (), m_object_name (), m_object_offset (0), + m_object_size (0), m_object_mod_time (), m_source_mappings () { @@ -42,6 +44,7 @@ class ModuleSpec m_uuid (), m_object_name (), m_object_offset (0), + m_object_size (file_spec.GetByteSize ()), m_object_mod_time (), m_source_mappings () { @@ -55,6 +58,7 @@ class ModuleSpec m_uuid (), m_object_name (), m_object_offset (0), + m_object_size (file_spec.GetByteSize ()), m_object_mod_time (), m_source_mappings () { @@ -68,6 +72,7 @@ class ModuleSpec m_uuid (rhs.m_uuid), m_object_name (rhs.m_object_name), m_object_offset (rhs.m_object_offset), + m_object_size (rhs.m_object_size), m_object_mod_time (rhs.m_object_mod_time), m_source_mappings (rhs.m_source_mappings) { @@ -85,6 +90,7 @@ class ModuleSpec m_uuid = rhs.m_uuid; m_object_name = rhs.m_object_name; m_object_offset = rhs.m_object_offset; + m_object_size = rhs.m_object_size; m_object_mod_time = rhs.m_object_mod_time; m_source_mappings = rhs.m_source_mappings; } @@ -254,7 +260,19 @@ class ModuleSpec { m_object_offset = object_offset; } - + + uint64_t + GetObjectSize () const + { + return m_object_size; + } + + void + SetObjectSize (uint64_t object_size) + { + m_object_size = object_size; + } + TimeValue & GetObjectModificationTime () { @@ -283,6 +301,7 @@ class ModuleSpec m_uuid.Clear(); m_object_name.Clear(); m_object_offset = 0; + m_object_size = 0; m_source_mappings.Clear(false); m_object_mod_time.Clear(); } @@ -302,6 +321,8 @@ class ModuleSpec return true; if (m_object_name) return true; + if (m_object_size) + return true; if (m_object_mod_time.IsValid()) return true; return false; @@ -362,7 +383,14 @@ class ModuleSpec { if (dumped_something) strm.PutCString(", "); - strm.Printf("object_offset = 0x%" PRIx64, m_object_offset); + strm.Printf("object_offset = %" PRIu64, m_object_offset); + dumped_something = true; + } + if (m_object_size > 0) + { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object size = %" PRIu64, m_object_size); dumped_something = true; } if (m_object_mod_time.IsValid()) @@ -425,6 +453,7 @@ class ModuleSpec UUID m_uuid; ConstString m_object_name; uint64_t m_object_offset; + uint64_t m_object_size; TimeValue m_object_mod_time; mutable PathMappingList m_source_mappings; }; diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h index 55e6df06d842..af940d788ab0 100644 --- a/include/lldb/Core/PluginManager.h +++ b/include/lldb/Core/PluginManager.h @@ -137,7 +137,8 @@ class PluginManager static bool RegisterPlugin (const ConstString &name, const char *description, - LanguageRuntimeCreateInstance create_callback); + LanguageRuntimeCreateInstance create_callback, + LanguageRuntimeGetCommandObject command_callback = nullptr); static bool UnregisterPlugin (LanguageRuntimeCreateInstance create_callback); @@ -145,6 +146,9 @@ class PluginManager static LanguageRuntimeCreateInstance GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx); + static LanguageRuntimeGetCommandObject + GetLanguageRuntimeGetCommandObjectAtIndex (uint32_t idx); + static LanguageRuntimeCreateInstance GetLanguageRuntimeCreateCallbackForPluginName (const ConstString &name); diff --git a/include/lldb/Core/RangeMap.h b/include/lldb/Core/RangeMap.h index d78504c7d285..d2c43a5d794d 100644 --- a/include/lldb/Core/RangeMap.h +++ b/include/lldb/Core/RangeMap.h @@ -128,9 +128,10 @@ namespace lldb_private { { return Contains(range.GetRangeBase()) && ContainsEndInclusive(range.GetRangeEnd()); } - + + // Returns true if the two ranges adjoing or intersect bool - Overlap (const Range &rhs) const + DoesAdjoinOrIntersect (const Range &rhs) const { const BaseType lhs_base = this->GetRangeBase(); const BaseType rhs_base = rhs.GetRangeBase(); @@ -139,7 +140,19 @@ namespace lldb_private { bool result = (lhs_base <= rhs_end) && (lhs_end >= rhs_base); return result; } - + + // Returns true if the two ranges intersect + bool + DoesIntersect (const Range &rhs) const + { + const BaseType lhs_base = this->GetRangeBase(); + const BaseType rhs_base = rhs.GetRangeBase(); + const BaseType lhs_end = this->GetRangeEnd(); + const BaseType rhs_end = rhs.GetRangeEnd(); + bool result = (lhs_base < rhs_end) && (lhs_end > rhs_base); + return result; + } + bool operator < (const Range &rhs) const { @@ -241,7 +254,7 @@ namespace lldb_private { // don't end up allocating and making a new collection for no reason for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) { can_combine = true; break; @@ -255,7 +268,7 @@ namespace lldb_private { Collection minimal_ranges; for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) minimal_ranges.back().SetRangeEnd (std::max(prev->GetRangeEnd(), pos->GetRangeEnd())); else minimal_ranges.push_back (*pos); @@ -521,7 +534,7 @@ namespace lldb_private { // don't end up allocating and making a new collection for no reason for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) { can_combine = true; break; @@ -535,7 +548,7 @@ namespace lldb_private { Collection minimal_ranges; for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { - if (prev != end && prev->Overlap(*pos)) + if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) minimal_ranges.back().SetRangeEnd (std::max(prev->GetRangeEnd(), pos->GetRangeEnd())); else minimal_ranges.push_back (*pos); diff --git a/include/lldb/Core/StreamAsynchronousIO.h b/include/lldb/Core/StreamAsynchronousIO.h index a73a9567fe83..d3b054463fa7 100644 --- a/include/lldb/Core/StreamAsynchronousIO.h +++ b/include/lldb/Core/StreamAsynchronousIO.h @@ -20,7 +20,7 @@ class StreamAsynchronousIO : public Stream { public: - StreamAsynchronousIO (Broadcaster &broadcaster, uint32_t broadcast_event_type); + StreamAsynchronousIO (Debugger &debugger, bool for_stdout); virtual ~StreamAsynchronousIO (); @@ -32,9 +32,9 @@ class StreamAsynchronousIO : private: - Broadcaster &m_broadcaster; - uint32_t m_broadcast_event_type; - std::string m_accumulated_data; + Debugger &m_debugger; + std::string m_data; + bool m_for_stdout; }; } // namespace lldb_private diff --git a/include/lldb/Core/StreamFile.h b/include/lldb/Core/StreamFile.h index d032c0b21e6b..55bb361780a5 100644 --- a/include/lldb/Core/StreamFile.h +++ b/include/lldb/Core/StreamFile.h @@ -37,6 +37,10 @@ class StreamFile : public Stream StreamFile (const char *path); + StreamFile (const char *path, + uint32_t options, + uint32_t permissions = lldb::eFilePermissionsFileDefault); + StreamFile (FILE *fh, bool transfer_ownership); virtual diff --git a/include/lldb/Core/StringList.h b/include/lldb/Core/StringList.h index b68ab4be2d6d..c69ed872c30d 100644 --- a/include/lldb/Core/StringList.h +++ b/include/lldb/Core/StringList.h @@ -14,6 +14,7 @@ #include "lldb/Core/STLUtils.h" #include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" namespace lldb_private { @@ -42,6 +43,9 @@ class StringList void AppendString (const char *str, size_t str_len); + void + AppendString(llvm::StringRef str); + void AppendList (const char ** strv, int strc); diff --git a/include/lldb/Core/StructuredData.h b/include/lldb/Core/StructuredData.h index a4cabf4fe352..8acfa310deac 100644 --- a/include/lldb/Core/StructuredData.h +++ b/include/lldb/Core/StructuredData.h @@ -13,10 +13,11 @@ // C Includes // C++ Includes +#include #include +#include #include #include -#include #include "llvm/ADT/StringRef.h" @@ -54,14 +55,22 @@ class StructuredData class Boolean; class String; class Dictionary; + class Generic; typedef std::shared_ptr ObjectSP; typedef std::shared_ptr ArraySP; + typedef std::shared_ptr IntegerSP; + typedef std::shared_ptr FloatSP; + typedef std::shared_ptr BooleanSP; + typedef std::shared_ptr StringSP; typedef std::shared_ptr DictionarySP; + typedef std::shared_ptr GenericSP; - enum class Type { + enum class Type + { eTypeInvalid = -1, eTypeNull = 0, + eTypeGeneric, eTypeArray, eTypeInteger, eTypeFloat, @@ -84,6 +93,12 @@ class StructuredData { } + virtual bool + IsValid() const + { + return true; + } + virtual void Clear () { @@ -126,6 +141,15 @@ class StructuredData return NULL; } + uint64_t + GetIntegerValue (uint64_t fail_value = 0) + { + Integer *integer = GetAsInteger (); + if (integer) + return integer->GetValue(); + return fail_value; + } + Float * GetAsFloat () { @@ -134,6 +158,15 @@ class StructuredData return NULL; } + double + GetFloatValue (double fail_value = 0.0) + { + Float *f = GetAsFloat (); + if (f) + return f->GetValue(); + return fail_value; + } + Boolean * GetAsBoolean () { @@ -142,6 +175,15 @@ class StructuredData return NULL; } + bool + GetBooleanValue (bool fail_value = false) + { + Boolean *b = GetAsBoolean (); + if (b) + return b->GetValue(); + return fail_value; + } + String * GetAsString () { @@ -150,9 +192,32 @@ class StructuredData return NULL; } + std::string + GetStringValue(const char *fail_value = NULL) + { + String *s = GetAsString (); + if (s) + return s->GetValue(); + + if (fail_value && fail_value[0]) + return std::string(fail_value); + + return std::string(); + } + + Generic * + GetAsGeneric() + { + if (m_type == Type::eTypeGeneric) + return (Generic *)this; + return NULL; + } + ObjectSP GetObjectForDotSeparatedPath (llvm::StringRef path); + void DumpToStdout() const; + virtual void Dump (Stream &s) const = 0; @@ -173,8 +238,19 @@ class StructuredData { } + void + ForEach (std::function const &foreach_callback) const + { + for (const auto &object_sp : m_items) + { + if (foreach_callback(object_sp.get()) == false) + break; + } + } + + size_t - GetSize() + GetSize() const { return m_items.size(); } @@ -188,13 +264,97 @@ class StructuredData } ObjectSP - GetItemAtIndex (size_t idx) + GetItemAtIndex(size_t idx) const { + assert(idx < GetSize()); if (idx < m_items.size()) return m_items[idx]; return ObjectSP(); } + template + bool + GetItemAtIndexAsInteger(size_t idx, IntType &result) const + { + ObjectSP value = GetItemAtIndex(idx); + if (auto int_value = value->GetAsInteger()) + { + result = static_cast(int_value->GetValue()); + return true; + } + return false; + } + + template + bool + GetItemAtIndexAsInteger(size_t idx, IntType &result, IntType default_val) const + { + bool success = GetItemAtIndexAsInteger(idx, result); + if (!success) + result = default_val; + return success; + } + + bool + GetItemAtIndexAsString(size_t idx, std::string &result) const + { + ObjectSP value = GetItemAtIndex(idx); + if (auto string_value = value->GetAsString()) + { + result = string_value->GetValue(); + return true; + } + return false; + } + + bool + GetItemAtIndexAsString(size_t idx, std::string &result, const std::string &default_val) const + { + bool success = GetItemAtIndexAsString(idx, result); + if (!success) + result = default_val; + return success; + } + + bool + GetItemAtIndexAsString(size_t idx, ConstString &result) const + { + ObjectSP value = GetItemAtIndex(idx); + if (!value) + return false; + if (auto string_value = value->GetAsString()) + { + result = ConstString(string_value->GetValue()); + return true; + } + return false; + } + + bool + GetItemAtIndexAsString(size_t idx, ConstString &result, const char *default_val) const + { + bool success = GetItemAtIndexAsString(idx, result); + if (!success) + result.SetCString(default_val); + return success; + } + + bool + GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const + { + ObjectSP value = GetItemAtIndex(idx); + result = value->GetAsDictionary(); + return (result != nullptr); + } + + bool + GetItemAtIndexAsArray(size_t idx, Array *&result) const + { + ObjectSP value = GetItemAtIndex(idx); + result = value->GetAsArray(); + return (result != nullptr); + } + void Push(ObjectSP item) { @@ -207,8 +367,7 @@ class StructuredData m_items.push_back(item); } - virtual void - Dump (Stream &s) const; + void Dump(Stream &s) const override; protected: typedef std::vector collection; @@ -219,9 +378,9 @@ class StructuredData class Integer : public Object { public: - Integer () : + Integer (uint64_t i = 0) : Object (Type::eTypeInteger), - m_value () + m_value (i) { } @@ -241,8 +400,7 @@ class StructuredData return m_value; } - virtual void - Dump (Stream &s) const; + void Dump(Stream &s) const override; protected: uint64_t m_value; @@ -251,9 +409,9 @@ class StructuredData class Float : public Object { public: - Float () : + Float (double d = 0.0) : Object (Type::eTypeFloat), - m_value () + m_value (d) { } @@ -273,8 +431,7 @@ class StructuredData return m_value; } - virtual void - Dump (Stream &s) const; + void Dump(Stream &s) const override; protected: double m_value; @@ -283,9 +440,9 @@ class StructuredData class Boolean : public Object { public: - Boolean () : + Boolean (bool b = false) : Object (Type::eTypeBoolean), - m_value () + m_value (b) { } @@ -305,8 +462,7 @@ class StructuredData return m_value; } - virtual void - Dump (Stream &s) const; + void Dump(Stream &s) const override; protected: bool m_value; @@ -317,26 +473,39 @@ class StructuredData class String : public Object { public: - String () : + String (const char *cstr = NULL) : Object (Type::eTypeString), m_value () + { + if (cstr) + m_value = cstr; + } + + String (const std::string &s) : + Object (Type::eTypeString), + m_value (s) + { + } + + String (const std::string &&s) : + Object (Type::eTypeString), + m_value (s) { } void - SetValue (std::string string) + SetValue (const std::string &string) { m_value = string; } - std::string + const std::string & GetValue () { return m_value; } - virtual void - Dump (Stream &s) const; + void Dump(Stream &s) const override; protected: std::string m_value; @@ -345,6 +514,7 @@ class StructuredData class Dictionary : public Object { public: + Dictionary () : Object (Type::eTypeDictionary), m_dict () @@ -354,14 +524,25 @@ class StructuredData virtual ~Dictionary() { } + size_t - GetSize() + GetSize() const { return m_dict.size(); } + void + ForEach (std::function const &callback) const + { + for (const auto &pair : m_dict) + { + if (callback (pair.first, pair.second.get()) == false) + break; + } + } + ObjectSP - GetKeys() + GetKeys() const { ObjectSP object_sp(new Array ()); Array *array = object_sp->GetAsArray(); @@ -376,10 +557,10 @@ class StructuredData } ObjectSP - GetValueForKey (const char *key) + GetValueForKey(llvm::StringRef key) const { ObjectSP value_sp; - if (key) + if (!key.empty()) { ConstString key_cs(key); for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter) @@ -394,62 +575,144 @@ class StructuredData return value_sp; } + template bool - HasKey (const char *key) + GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const { - ConstString key_cs (key); - collection::const_iterator search = m_dict.find(key_cs); - if (search != m_dict.end()) + ObjectSP value = GetValueForKey(key); + if (!value) + return false; + if (auto int_value = value->GetAsInteger()) { + result = static_cast(int_value->GetValue()); return true; } - else - { + return false; + } + + template + bool + GetValueForKeyAsInteger(llvm::StringRef key, IntType &result, IntType default_val) const + { + bool success = GetValueForKeyAsInteger(key, result); + if (!success) + result = default_val; + return success; + } + + bool + GetValueForKeyAsString(llvm::StringRef key, std::string &result) const + { + ObjectSP value = GetValueForKey(key); + if (!value) return false; + if (auto string_value = value->GetAsString()) + { + result = string_value->GetValue(); + return true; } + return false; + } + + bool + GetValueForKeyAsString(llvm::StringRef key, std::string &result, const char *default_val) const + { + bool success = GetValueForKeyAsString(key, result); + if (!success) + { + if (default_val) + result = default_val; + else + result.clear(); + } + return success; + } + + bool + GetValueForKeyAsString(llvm::StringRef key, ConstString &result) const + { + ObjectSP value = GetValueForKey(key); + if (!value) + return false; + if (auto string_value = value->GetAsString()) + { + result = ConstString(string_value->GetValue()); + return true; + } + return false; + } + + bool + GetValueForKeyAsString(llvm::StringRef key, ConstString &result, const char *default_val) const + { + bool success = GetValueForKeyAsString(key, result); + if (!success) + result.SetCString(default_val); + return success; + } + + bool + GetValueForKeyAsDictionary(llvm::StringRef key, Dictionary *&result) const + { + result = nullptr; + ObjectSP value = GetValueForKey(key); + if (!value) + return false; + result = value->GetAsDictionary(); + return true; + } + + bool + GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const + { + result = nullptr; + ObjectSP value = GetValueForKey(key); + if (!value) + return false; + result = value->GetAsArray(); + return true; + } + + bool + HasKey(llvm::StringRef key) const + { + ConstString key_cs(key); + collection::const_iterator search = m_dict.find(key_cs); + return search != m_dict.end(); } void - AddItem (const char *key, ObjectSP value) + AddItem (llvm::StringRef key, ObjectSP value) { ConstString key_cs(key); m_dict[key_cs] = value; } void - AddIntegerItem (const char *key, uint64_t value) + AddIntegerItem (llvm::StringRef key, uint64_t value) { - ObjectSP val_obj (new Integer()); - val_obj->GetAsInteger()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new Integer(value))); } void - AddFloatItem (const char *key, double value) + AddFloatItem (llvm::StringRef key, double value) { - ObjectSP val_obj (new Float()); - val_obj->GetAsFloat()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new Float(value))); } void - AddStringItem (const char *key, std::string value) + AddStringItem (llvm::StringRef key, std::string value) { - ObjectSP val_obj (new String()); - val_obj->GetAsString()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new String(std::move(value)))); } void - AddBooleanItem (const char *key, bool value) + AddBooleanItem (llvm::StringRef key, bool value) { - ObjectSP val_obj (new Boolean()); - val_obj->GetAsBoolean()->SetValue (value); - AddItem (key, val_obj); + AddItem (key, ObjectSP (new Boolean(value))); } - virtual void - Dump (Stream &s) const; + void Dump(Stream &s) const override; protected: typedef std::map collection; @@ -468,12 +731,49 @@ class StructuredData { } - virtual void - Dump (Stream &s) const; + bool + IsValid() const override + { + return false; + } + + void Dump(Stream &s) const override; protected: }; + class Generic : public Object + { + public: + explicit Generic(void *object = nullptr) : + Object (Type::eTypeGeneric), + m_object (object) + { + } + + void + SetValue(void *value) + { + m_object = value; + } + + void * + GetValue() const + { + return m_object; + } + + bool + IsValid() const override + { + return m_object != nullptr; + } + + void Dump(Stream &s) const override; + + private: + void *m_object; + }; static ObjectSP ParseJSON (std::string json_text); diff --git a/include/lldb/Core/ThreadSafeDenseSet.h b/include/lldb/Core/ThreadSafeDenseSet.h new file mode 100644 index 000000000000..19c67b65e8c1 --- /dev/null +++ b/include/lldb/Core/ThreadSafeDenseSet.h @@ -0,0 +1,65 @@ +//===-- ThreadSafeDenseSet.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeDenseSet_h_ +#define liblldb_ThreadSafeDenseSet_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +#include "llvm/ADT/DenseSet.h" + +// Project includes +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + + template + class ThreadSafeDenseSet + { + public: + typedef llvm::DenseSet<_ElementType> LLVMSetType; + + ThreadSafeDenseSet(unsigned set_initial_capacity = 0, + Mutex::Type mutex_type = Mutex::eMutexTypeNormal) : + m_set(set_initial_capacity), + m_mutex(mutex_type) + { + } + + void + Insert (_ElementType e) + { + Mutex::Locker locker(m_mutex); + m_set.insert(e); + } + + void + Erase (_ElementType e) + { + Mutex::Locker locker(m_mutex); + m_set.erase(e); + } + + bool + Lookup (_ElementType e) + { + Mutex::Locker locker(m_mutex); + return (m_set.count(e) > 0); + } + + protected: + LLVMSetType m_set; + Mutex m_mutex; + }; + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeDenseSet_h_ diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h index b50adfb69564..cdc507093b28 100644 --- a/include/lldb/Core/ValueObject.h +++ b/include/lldb/Core/ValueObject.h @@ -16,6 +16,7 @@ #include // Other libraries and framework includes +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" // Project includes @@ -26,6 +27,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/UserID.h" #include "lldb/Core/Value.h" +#include "lldb/Symbol/ClangASTType.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Process.h" @@ -139,19 +141,27 @@ class ValueObject : public UserID struct GetValueForExpressionPathOptions { + enum class SyntheticChildrenTraversal + { + None, + ToSynthetic, + FromSynthetic, + Both + }; + bool m_check_dot_vs_arrow_syntax; bool m_no_fragile_ivar; bool m_allow_bitfields_syntax; - bool m_no_synthetic_children; + SyntheticChildrenTraversal m_synthetic_children_traversal; GetValueForExpressionPathOptions(bool dot = false, bool no_ivar = false, bool bitfield = true, - bool no_synth = false) : + SyntheticChildrenTraversal synth_traverse = SyntheticChildrenTraversal::ToSynthetic) : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar), m_allow_bitfields_syntax(bitfield), - m_no_synthetic_children(no_synth) + m_synthetic_children_traversal(synth_traverse) { } @@ -198,16 +208,9 @@ class ValueObject : public UserID } GetValueForExpressionPathOptions& - DoAllowSyntheticChildren() + SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) { - m_no_synthetic_children = false; - return *this; - } - - GetValueForExpressionPathOptions& - DontAllowSyntheticChildren() - { - m_no_synthetic_children = true; + m_synthetic_children_traversal = traverse; return *this; } @@ -282,18 +285,19 @@ class ValueObject : public UserID SetUpdated (); bool - NeedsUpdating() + NeedsUpdating(bool accept_invalid_exe_ctx) { - SyncWithProcessState(); + SyncWithProcessState(accept_invalid_exe_ctx); return m_needs_update; } bool IsValid () { + const bool accept_invalid_exe_ctx = false; if (!m_mod_id.IsValid()) return false; - else if (SyncWithProcessState ()) + else if (SyncWithProcessState (accept_invalid_exe_ctx)) { if (!m_mod_id.IsValid()) return false; @@ -315,7 +319,7 @@ class ValueObject : public UserID private: bool - SyncWithProcessState (); + SyncWithProcessState (bool accept_invalid_exe_ctx); ProcessModID m_mod_id; // This is the stop id when this ValueObject was last evaluated. ExecutionContextRef m_exe_ctx_ref; @@ -647,6 +651,7 @@ class ValueObject : public UserID bool GetValueIsValid () const; + // If you call this on a newly created ValueObject, it will always return false. bool GetValueDidChange (); @@ -678,12 +683,6 @@ class ValueObject : public UserID lldb::ValueObjectSP GetSyntheticArrayMember (size_t index, bool can_create); - lldb::ValueObjectSP - GetSyntheticArrayMemberFromPointer (size_t index, bool can_create); - - lldb::ValueObjectSP - GetSyntheticArrayMemberFromArray (size_t index, bool can_create); - lldb::ValueObjectSP GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create); @@ -853,12 +852,19 @@ class ValueObject : public UserID virtual bool SetData (DataExtractor &data, Error &error); - bool + virtual bool GetIsConstant () const { return m_update_point.IsConstant(); } + bool + NeedsUpdating () + { + const bool accept_invalid_exe_ctx = CanUpdateWithInvalidExecutionContext(); + return m_update_point.NeedsUpdating(accept_invalid_exe_ctx); + } + void SetIsConstant () { @@ -868,7 +874,7 @@ class ValueObject : public UserID lldb::Format GetFormat () const; - void + virtual void SetFormat (lldb::Format format) { if (format != m_format) @@ -992,6 +998,9 @@ class ValueObject : public UserID //------------------------------------------------------------------ virtual bool MightHaveChildren(); + + virtual bool + IsRuntimeSupportValue (); protected: typedef ClusterManager ValueObjectManager; @@ -1128,10 +1137,12 @@ class ValueObject : public UserID m_did_calculate_complete_objc_class_type:1, m_is_synthetic_children_generated:1; + friend class ValueObjectChild; friend class ClangExpressionDeclMap; // For GetValue friend class ClangExpressionVariable; // For SetName friend class Target; // For SetName friend class ValueObjectConstResultImpl; + friend class ValueObjectSynthetic; // For ClearUserVisibleData //------------------------------------------------------------------ // Constructors and Destructors @@ -1161,6 +1172,12 @@ class ValueObject : public UserID virtual bool UpdateValue () = 0; + virtual bool + CanUpdateWithInvalidExecutionContext () + { + return false; + } + virtual void CalculateDynamicValue (lldb::DynamicValueType use_dynamic); diff --git a/include/lldb/Core/ValueObjectChild.h b/include/lldb/Core/ValueObjectChild.h index 7bbfe8a662d1..bf8707ea3b05 100644 --- a/include/lldb/Core/ValueObjectChild.h +++ b/include/lldb/Core/ValueObjectChild.h @@ -83,6 +83,9 @@ class ValueObjectChild : public ValueObject protected: virtual bool UpdateValue (); + + virtual bool + CanUpdateWithInvalidExecutionContext (); virtual ClangASTType GetClangTypeImpl () diff --git a/include/lldb/Core/ValueObjectDynamicValue.h b/include/lldb/Core/ValueObjectDynamicValue.h index 7607bd38137d..8d42706be166 100644 --- a/include/lldb/Core/ValueObjectDynamicValue.h +++ b/include/lldb/Core/ValueObjectDynamicValue.h @@ -56,6 +56,12 @@ class ValueObjectDynamicValue : public ValueObject return true; } + virtual bool + GetIsConstant () const + { + return false; + } + virtual ValueObject * GetParent() { @@ -103,6 +109,12 @@ class ValueObjectDynamicValue : public ValueObject virtual bool UpdateValue (); + virtual bool + CanUpdateWithInvalidExecutionContext () + { + return true; + } + virtual lldb::DynamicValueType GetDynamicValueTypeImpl () { diff --git a/include/lldb/Core/ValueObjectSyntheticFilter.h b/include/lldb/Core/ValueObjectSyntheticFilter.h index aa784add7409..88824ef4fa54 100644 --- a/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -140,13 +140,28 @@ class ValueObjectSynthetic : public ValueObject return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes); } + virtual bool + GetIsConstant () const + { + return false; + } + virtual bool SetValueFromCString (const char *value_str, Error& error); + virtual void + SetFormat (lldb::Format format); + protected: virtual bool UpdateValue (); + virtual bool + CanUpdateWithInvalidExecutionContext () + { + return true; + } + virtual ClangASTType GetClangTypeImpl (); diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h index 53b7468bb13c..9b1a02ca0a5c 100644 --- a/include/lldb/DataFormatters/CXXFormatterFunctions.h +++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h @@ -186,6 +186,9 @@ namespace lldb_private { extern template bool ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&); + bool + CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); + SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); @@ -229,37 +232,6 @@ namespace lldb_private { bool LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - class LibstdcppVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibstdcppVectorBoolSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint64_t m_count; - lldb::addr_t m_base_data_address; - EvaluateExpressionOptions m_options; - }; - - SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -395,6 +367,7 @@ namespace lldb_private { SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + SyntheticChildrenFrontEnd* VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); } // namespace formatters } // namespace lldb_private diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h index 37dae6536761..a1f4b59fb344 100644 --- a/include/lldb/DataFormatters/FormatManager.h +++ b/include/lldb/DataFormatters/FormatManager.h @@ -287,6 +287,7 @@ class FormatManager : public IFormatChangeListener ConstString m_coreservices_category_name; ConstString m_vectortypes_category_name; ConstString m_appkit_category_name; + ConstString m_coremedia_category_name; HardcodedFormatterFinders m_hardcoded_formats; HardcodedFormatterFinders m_hardcoded_summaries; @@ -326,6 +327,9 @@ class FormatManager : public IFormatChangeListener void LoadObjCFormatters (); + + void + LoadCoreMediaFormatters (); void LoadHardcodedFormatters (); diff --git a/include/lldb/DataFormatters/TypeFormat.h b/include/lldb/DataFormatters/TypeFormat.h index 1090d7843e53..8aa7c60b4938 100644 --- a/include/lldb/DataFormatters/TypeFormat.h +++ b/include/lldb/DataFormatters/TypeFormat.h @@ -115,6 +115,22 @@ namespace lldb_private { return *this; } + bool + GetNonCacheable () const + { + return (m_flags & lldb::eTypeOptionNonCacheable) == lldb::eTypeOptionNonCacheable; + } + + Flags& + SetNonCacheable (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionNonCacheable; + else + m_flags &= ~lldb::eTypeOptionNonCacheable; + return *this; + } + uint32_t GetValue () { @@ -153,6 +169,11 @@ namespace lldb_private { { return m_flags.GetSkipReferences(); } + bool + NonCacheable () const + { + return m_flags.GetNonCacheable(); + } void SetCascades (bool value) @@ -171,6 +192,12 @@ namespace lldb_private { { m_flags.SetSkipReferences(value); } + + void + SetNonCacheable (bool value) + { + m_flags.SetNonCacheable(value); + } uint32_t GetOptions () diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h index 8b90dd0c4895..c2838eac27f1 100644 --- a/include/lldb/DataFormatters/TypeSummary.h +++ b/include/lldb/DataFormatters/TypeSummary.h @@ -25,8 +25,8 @@ #include "lldb/Core/Error.h" #include "lldb/Core/FormatEntity.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Symbol/Type.h" namespace lldb_private { @@ -211,6 +211,22 @@ namespace lldb_private { return *this; } + bool + GetNonCacheable () const + { + return (m_flags & lldb::eTypeOptionNonCacheable) == lldb::eTypeOptionNonCacheable; + } + + Flags& + SetNonCacheable (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionNonCacheable; + else + m_flags &= ~lldb::eTypeOptionNonCacheable; + return *this; + } + uint32_t GetValue () { @@ -252,6 +268,11 @@ namespace lldb_private { { return m_flags.GetSkipReferences(); } + bool + NonCacheable () const + { + return m_flags.GetNonCacheable(); + } virtual bool DoesPrintChildren (ValueObject* valobj) const @@ -319,6 +340,12 @@ namespace lldb_private { m_flags.SetHideItemNames(value); } + virtual void + SetNonCacheable (bool value) + { + m_flags.SetNonCacheable(value); + } + uint32_t GetOptions () { @@ -501,8 +528,8 @@ namespace lldb_private { { std::string m_function_name; std::string m_python_script; - lldb::ScriptInterpreterObjectSP m_script_function_sp; - + StructuredData::ObjectSP m_script_function_sp; + ScriptSummaryFormat(const TypeSummaryImpl::Flags& flags, const char *function_name, const char* python_script = NULL); diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h index 675c43b1f311..ff6691c9a1b8 100644 --- a/include/lldb/DataFormatters/TypeSynthetic.h +++ b/include/lldb/DataFormatters/TypeSynthetic.h @@ -23,6 +23,7 @@ #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Core/ValueObject.h" namespace lldb_private { @@ -235,6 +236,22 @@ namespace lldb_private { return *this; } + bool + GetNonCacheable () const + { + return (m_flags & lldb::eTypeOptionNonCacheable) == lldb::eTypeOptionNonCacheable; + } + + Flags& + SetNonCacheable (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionNonCacheable; + else + m_flags &= ~lldb::eTypeOptionNonCacheable; + return *this; + } + uint32_t GetValue () { @@ -276,6 +293,11 @@ namespace lldb_private { { return m_flags.GetSkipReferences(); } + bool + NonCacheable () const + { + return m_flags.GetNonCacheable(); + } void SetCascades (bool value) @@ -295,6 +317,12 @@ namespace lldb_private { m_flags.SetSkipReferences(value); } + void + SetNonCacheable (bool value) + { + m_flags.SetNonCacheable(value); + } + uint32_t GetOptions () { @@ -551,7 +579,7 @@ namespace lldb_private { { private: std::string m_python_class; - lldb::ScriptInterpreterObjectSP m_wrapper_sp; + StructuredData::ObjectSP m_wrapper_sp; ScriptInterpreter *m_interpreter; public: diff --git a/include/lldb/DataFormatters/TypeValidator.h b/include/lldb/DataFormatters/TypeValidator.h index b501e47943fa..d06fac01f824 100644 --- a/include/lldb/DataFormatters/TypeValidator.h +++ b/include/lldb/DataFormatters/TypeValidator.h @@ -115,6 +115,22 @@ class TypeValidatorImpl return *this; } + bool + GetNonCacheable () const + { + return (m_flags & lldb::eTypeOptionNonCacheable) == lldb::eTypeOptionNonCacheable; + } + + Flags& + SetNonCacheable (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionNonCacheable; + else + m_flags &= ~lldb::eTypeOptionNonCacheable; + return *this; + } + uint32_t GetValue () { @@ -153,6 +169,11 @@ class TypeValidatorImpl { return m_flags.GetSkipReferences(); } + bool + NonCacheable () const + { + return m_flags.GetNonCacheable(); + } void SetCascades (bool value) @@ -172,6 +193,12 @@ class TypeValidatorImpl m_flags.SetSkipReferences(value); } + void + SetNonCacheable (bool value) + { + m_flags.SetNonCacheable(value); + } + uint32_t GetOptions () { diff --git a/include/lldb/DataFormatters/ValueObjectPrinter.h b/include/lldb/DataFormatters/ValueObjectPrinter.h index 235d5389ee75..dc05fd482676 100644 --- a/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -75,6 +75,8 @@ struct DumpValueObjectOptions DumpValueObjectOptions (const DumpValueObjectOptions& rhs) = default; + DumpValueObjectOptions (ValueObject& valobj); + DumpValueObjectOptions& SetMaximumPointerDepth(uint32_t depth = 0) { @@ -246,6 +248,9 @@ struct DumpValueObjectOptions class ValueObjectPrinter { public: + + ValueObjectPrinter (ValueObject* valobj, + Stream* s); ValueObjectPrinter (ValueObject* valobj, Stream* s, diff --git a/tools/lldb-platform/exports b/include/lldb/DataFormatters/VectorType.h similarity index 100% rename from tools/lldb-platform/exports rename to include/lldb/DataFormatters/VectorType.h diff --git a/include/lldb/Expression/ClangASTSource.h b/include/lldb/Expression/ClangASTSource.h index 3e41a9e69e9b..46140d2f2e64 100644 --- a/include/lldb/Expression/ClangASTSource.h +++ b/include/lldb/Expression/ClangASTSource.h @@ -15,6 +15,7 @@ #include "clang/Basic/IdentifierTable.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/ClangASTType.h" #include "lldb/Target/Target.h" #include "llvm/ADT/SmallSet.h" @@ -45,39 +46,40 @@ class ClangASTSource : /// @param[in] declMap /// A reference to the LLDB object that handles entity lookup. //------------------------------------------------------------------ - ClangASTSource (const lldb::TargetSP &target) : + ClangASTSource (const lldb::TargetSP &target) : m_import_in_progress (false), m_lookups_enabled (false), m_target (target), m_ast_context (NULL), + m_active_lexical_decls (), m_active_lookups () { m_ast_importer = m_target->GetClangASTImporter(); } - + //------------------------------------------------------------------ /// Destructor //------------------------------------------------------------------ - ~ClangASTSource(); - + ~ClangASTSource(); + //------------------------------------------------------------------ /// Interface stubs. //------------------------------------------------------------------ - clang::Decl *GetExternalDecl (uint32_t) { return NULL; } - clang::Stmt *GetExternalDeclStmt (uint64_t) { return NULL; } - clang::Selector GetExternalSelector (uint32_t) { return clang::Selector(); } - uint32_t GetNumExternalSelectors () { return 0; } - clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) + clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } + clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } + clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } + uint32_t GetNumExternalSelectors () override { return 0; } + clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override { return NULL; } void MaterializeVisibleDecls (const clang::DeclContext *DC) { return; } - + void InstallASTContext (clang::ASTContext *ast_context) { m_ast_context = ast_context; m_ast_importer->InstallMapCompleter(ast_context, *this); } - + // // APIs for ExternalASTSource // @@ -100,10 +102,8 @@ class ClangASTSource : /// @return /// Whatever SetExternalVisibleDeclsForName returns. //------------------------------------------------------------------ - bool - FindExternalVisibleDeclsByName (const clang::DeclContext *DC, - clang::DeclarationName Name); - + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; + //------------------------------------------------------------------ /// Enumerate all Decls in a given lexical context. /// @@ -117,11 +117,10 @@ class ClangASTSource : /// @param[in] Decls /// A vector that is filled in with matching Decls. //------------------------------------------------------------------ - clang::ExternalLoadResult - FindExternalLexicalDecls (const clang::DeclContext *DC, - bool (*isKindWeWant)(clang::Decl::Kind), - llvm::SmallVectorImpl &Decls); - + clang::ExternalLoadResult FindExternalLexicalDecls(const clang::DeclContext *DC, + bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl &Decls) override; + //------------------------------------------------------------------ /// Specify the layout of the contents of a RecordDecl. /// @@ -154,33 +153,28 @@ class ClangASTSource : /// /// @return /// True <=> the layout is valid. - //----------------------------------------------------------------- - bool - layoutRecordType(const clang::RecordDecl *Record, - uint64_t &Size, - uint64_t &Alignment, - llvm::DenseMap &FieldOffsets, - llvm::DenseMap &BaseOffsets, - llvm::DenseMap &VirtualBaseOffsets); - + //----------------------------------------------------------------- + bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override; + //------------------------------------------------------------------ /// Complete a TagDecl. /// /// @param[in] Tag /// The Decl to be completed in place. //------------------------------------------------------------------ - virtual void - CompleteType (clang::TagDecl *Tag); - + void CompleteType(clang::TagDecl *Tag) override; + //------------------------------------------------------------------ /// Complete an ObjCInterfaceDecl. /// /// @param[in] Class /// The Decl to be completed in place. //------------------------------------------------------------------ - virtual void - CompleteType (clang::ObjCInterfaceDecl *Class); - + void CompleteType(clang::ObjCInterfaceDecl *Class) override; + //------------------------------------------------------------------ /// Called on entering a translation unit. Tells Clang by calling /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() @@ -189,8 +183,8 @@ class ClangASTSource : /// @param[in] ASTConsumer /// Unused. //------------------------------------------------------------------ - void StartTranslationUnit (clang::ASTConsumer *Consumer); - + void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + // // APIs for NamespaceMapCompleter // @@ -209,10 +203,9 @@ class ClangASTSource : /// The map for the namespace's parent namespace, if there is /// one. //------------------------------------------------------------------ - void CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, - const ConstString &name, - ClangASTImporter::NamespaceMapSP &parent_map) const; - + void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const override; + // // Helper APIs // @@ -249,41 +242,37 @@ class ClangASTSource : m_original(original) { } - + bool - FindExternalVisibleDeclsByName (const clang::DeclContext *DC, - clang::DeclarationName Name) + FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override { return m_original.FindExternalVisibleDeclsByName(DC, Name); } - - clang::ExternalLoadResult - FindExternalLexicalDecls (const clang::DeclContext *DC, - bool (*isKindWeWant)(clang::Decl::Kind), - llvm::SmallVectorImpl &Decls) + + clang::ExternalLoadResult + FindExternalLexicalDecls(const clang::DeclContext *DC, bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl &Decls) override { return m_original.FindExternalLexicalDecls(DC, isKindWeWant, Decls); } - + void - CompleteType (clang::TagDecl *Tag) + CompleteType(clang::TagDecl *Tag) override { return m_original.CompleteType(Tag); } - - void - CompleteType (clang::ObjCInterfaceDecl *Class) + + void + CompleteType(clang::ObjCInterfaceDecl *Class) override { return m_original.CompleteType(Class); } - - bool - layoutRecordType(const clang::RecordDecl *Record, - uint64_t &Size, - uint64_t &Alignment, - llvm::DenseMap &FieldOffsets, - llvm::DenseMap &BaseOffsets, - llvm::DenseMap &VirtualBaseOffsets) + + bool + layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override { return m_original.layoutRecordType(Record, Size, @@ -293,7 +282,8 @@ class ClangASTSource : VirtualBaseOffsets); } - void StartTranslationUnit (clang::ASTConsumer *Consumer) + void + StartTranslationUnit(clang::ASTConsumer *Consumer) override { return m_original.StartTranslationUnit(Consumer); } @@ -413,8 +403,9 @@ class ClangASTSource : bool m_lookups_enabled; const lldb::TargetSP m_target; ///< The target to use in finding variables and types. - clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. ClangASTImporter *m_ast_importer; ///< The target's AST importer. + std::set m_active_lexical_decls; std::set m_active_lookups; }; @@ -485,8 +476,12 @@ struct NameSearchContext { /// /// @param[in] type /// The opaque QualType for the FunDecl being registered. + /// + /// @param[in] extern_c + /// If true, build an extern "C" linkage specification for this. //------------------------------------------------------------------ - clang::NamedDecl *AddFunDecl(const ClangASTType &type); + clang::NamedDecl *AddFunDecl(const ClangASTType &type, + bool extern_c = false); //------------------------------------------------------------------ /// Create a FunDecl with the name being searched for and generic @@ -513,7 +508,7 @@ struct NameSearchContext { /// The DeclContextLookupResult, usually returned as the result /// of querying a DeclContext. //------------------------------------------------------------------ - void AddLookupResult (clang::DeclContextLookupConstResult result); + void AddLookupResult (clang::DeclContextLookupResult result); //------------------------------------------------------------------ /// Add a NamedDecl to the list of results. diff --git a/include/lldb/Expression/ClangExpressionDeclMap.h b/include/lldb/Expression/ClangExpressionDeclMap.h index 8a4aa82b8727..f24500ab5237 100644 --- a/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/include/lldb/Expression/ClangExpressionDeclMap.h @@ -100,6 +100,9 @@ class ClangExpressionDeclMap : WillParse (ExecutionContext &exe_ctx, Materializer *materializer); + void + InstallCodeGenerator (clang::ASTConsumer *code_gen); + //------------------------------------------------------------------ /// [Used by ClangExpressionParser] For each variable that had an unknown /// type at the beginning of parsing, determine its final type now. @@ -396,11 +399,6 @@ class ClangExpressionDeclMap : { public: ParserVars(ClangExpressionDeclMap &decl_map) : - m_exe_ctx(), - m_sym_ctx(), - m_persistent_vars(NULL), - m_enable_lookups(false), - m_materializer(NULL), m_decl_map(decl_map) { } @@ -415,12 +413,13 @@ class ClangExpressionDeclMap : return NULL; } - ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. - SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. - ClangPersistentVariables *m_persistent_vars; ///< The persistent variables for the process. - bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name. - TargetInfo m_target_info; ///< Basic information about the target. - Materializer *m_materializer; ///< If non-NULL, the materializer to use when reporting used variables. + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. + ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. + bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables. + clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions. private: ClangExpressionDeclMap &m_decl_map; DISALLOW_COPY_AND_ASSIGN (ParserVars); diff --git a/include/lldb/Expression/ClangExpressionParser.h b/include/lldb/Expression/ClangExpressionParser.h index 0f578c55942e..21a27a489bcd 100644 --- a/include/lldb/Expression/ClangExpressionParser.h +++ b/include/lldb/Expression/ClangExpressionParser.h @@ -145,7 +145,6 @@ class ClangExpressionParser std::unique_ptr m_compiler; ///< The Clang compiler used to parse expressions into IR std::unique_ptr m_builtin_context; ///< Context for Clang built-ins std::unique_ptr m_selector_table; ///< Selector table for Objective-C methods - std::unique_ptr m_ast_context; ///< The AST context used to hold types and names for the parser std::unique_ptr m_code_generator; ///< The Clang object that generates IR class LLDBPreprocessorCallbacks; diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h index c122b21be279..cf7e2592021f 100644 --- a/include/lldb/Expression/ClangFunction.h +++ b/include/lldb/Expression/ClangFunction.h @@ -22,6 +22,7 @@ #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Expression/ClangExpression.h" +#include "lldb/Symbol/ClangASTType.h" #include "lldb/Target/Process.h" namespace lldb_private @@ -412,7 +413,7 @@ class ClangFunction : public ClangExpression //------------------------------------------------------------------ // Note: the parser needs to be destructed before the execution unit, so - // declare the the execution unit first. + // declare the execution unit first. std::shared_ptr m_execution_unit_sp; std::unique_ptr m_parser; ///< The parser responsible for compiling the function. lldb::ModuleWP m_jit_module_wp; diff --git a/include/lldb/Expression/ClangModulesDeclVendor.h b/include/lldb/Expression/ClangModulesDeclVendor.h index a35b86a665ff..a8297c8fa331 100644 --- a/include/lldb/Expression/ClangModulesDeclVendor.h +++ b/include/lldb/Expression/ClangModulesDeclVendor.h @@ -15,6 +15,7 @@ #include "lldb/Symbol/DeclVendor.h" #include "lldb/Target/Platform.h" +#include #include namespace lldb_private @@ -34,6 +35,10 @@ class ClangModulesDeclVendor : public DeclVendor static ClangModulesDeclVendor * Create(Target &target); + typedef std::vector ModulePath; + typedef uintptr_t ModuleID; + typedef std::vector ModuleVector; + //------------------------------------------------------------------ /// Add a module to the list of modules to search. /// @@ -41,6 +46,10 @@ class ClangModulesDeclVendor : public DeclVendor /// The path to the exact module to be loaded. E.g., if the desired /// module is std.io, then this should be { "std", "io" }. /// + /// @param[in] exported_modules + /// If non-NULL, a pointer to a vector to populate with the ID of every + /// module that is re-exported by the specified module. + /// /// @param[in] error_stream /// A stream to populate with the output of the Clang parser when /// it tries to load the module. @@ -51,7 +60,69 @@ class ClangModulesDeclVendor : public DeclVendor /// load, then this will always return false for this ModuleImporter. //------------------------------------------------------------------ virtual bool - AddModule(std::vector &path, Stream &error_stream) = 0; + AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Add all modules referred to in a given compilation unit to the list + /// of modules to search. + /// + /// @param[in] cu + /// The compilation unit to scan for imported modules. + /// + /// @param[in] exported_modules + /// A vector to populate with the ID of each module loaded (directly + /// and via re-exports) in this way. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the modules. + /// + /// @return + /// True if all modules referred to by the compilation unit could be + /// loaded; false if one could not be loaded. If the compiler + /// encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Enumerate all the macros that are defined by a given set of modules + /// that are already imported. + /// + /// @param[in] modules + /// The unique IDs for all modules to query. Later modules have higher + /// priority, just as if you @imported them in that order. This matters + /// if module A #defines a macro and module B #undefs it. + /// + /// @param[in] handler + /// A function to call with the text of each #define (including the + /// #define directive). #undef directives are not included; we simply + /// elide any corresponding #define. If this function returns true, + /// we stop the iteration immediately. + //------------------------------------------------------------------ + virtual void + ForEachMacro(const ModuleVector &modules, + std::function handler) = 0; + + //------------------------------------------------------------------ + /// Query whether Clang supports modules for a particular language. + /// LLDB uses this to decide whether to try to find the modules loaded + /// by a gaiven compile unit. + /// + /// @param[in] language + /// The language to query for. + /// + /// @return + /// True if Clang has modules for the given language. + //------------------------------------------------------------------ + static bool + LanguageSupportsClangModules (lldb::LanguageType language); + }; } diff --git a/include/lldb/Expression/ClangPersistentVariables.h b/include/lldb/Expression/ClangPersistentVariables.h index 6d9dae954734..247f87fae41b 100644 --- a/include/lldb/Expression/ClangPersistentVariables.h +++ b/include/lldb/Expression/ClangPersistentVariables.h @@ -11,6 +11,8 @@ #define liblldb_ClangPersistentVariables_h_ #include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/ClangModulesDeclVendor.h" + #include "llvm/ADT/DenseMap.h" namespace lldb_private @@ -63,11 +65,25 @@ class ClangPersistentVariables : public ClangExpressionVariableList clang::TypeDecl * GetPersistentType (const ConstString &name); + void + AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) + { + m_hand_loaded_clang_modules.push_back(module); + } + + const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() + { + return m_hand_loaded_clang_modules; + } + private: uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). typedef llvm::DenseMap PersistentTypeMap; PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. + + ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest- + ///< priority source for macros. }; } diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h index f51c9851789a..dbea48148e14 100644 --- a/include/lldb/Expression/ClangUserExpression.h +++ b/include/lldb/Expression/ClangUserExpression.h @@ -45,8 +45,7 @@ namespace lldb_private class ClangUserExpression : public ClangExpression { public: - typedef std::shared_ptr ClangUserExpressionSP; - + enum { kDefaultTimeout = 500000u }; //------------------------------------------------------------------ /// Constructor @@ -146,7 +145,7 @@ class ClangUserExpression : public ClangExpression Execute (Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, - ClangUserExpressionSP &shared_ptr_to_me, + lldb::ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result); //------------------------------------------------------------------ @@ -307,7 +306,7 @@ class ClangUserExpression : public ClangExpression static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. private: //------------------------------------------------------------------ - /// Populate m_cplusplus and m_objectivec based on the environment. + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. //------------------------------------------------------------------ void @@ -349,9 +348,9 @@ class ClangUserExpression : public ClangExpression std::unique_ptr m_result_synthesizer; ///< The result synthesizer, if one is needed. lldb::ModuleWP m_jit_module_wp; bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer in order to generate the expression as a method. - bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method). - bool m_objectivec; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method). - bool m_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it was parsed when exe_ctx was in an Objective-C class method). + bool m_in_cplusplus_method; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method). + bool m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method). + bool m_in_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it was parsed when exe_ctx was in an Objective-C class method). bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL. bool m_const_object; ///< True if "this" is const. Target *m_target; ///< The target for storing persistent data like types and variables. diff --git a/include/lldb/Expression/IRForTarget.h b/include/lldb/Expression/IRForTarget.h index 0ad34904f563..b81fab7a8a83 100644 --- a/include/lldb/Expression/IRForTarget.h +++ b/include/lldb/Expression/IRForTarget.h @@ -640,6 +640,9 @@ class IRForTarget : public llvm::ModulePass return m_stream_string; } lldb::addr_t Allocate(); + + lldb::TargetSP + GetTarget(); private: lldb_private::IRExecutionUnit &m_execution_unit; lldb_private::StreamString m_stream_string; diff --git a/include/lldb/Expression/IRMemoryMap.h b/include/lldb/Expression/IRMemoryMap.h index 4faa5226d9b4..0da8384c8e63 100644 --- a/include/lldb/Expression/IRMemoryMap.h +++ b/include/lldb/Expression/IRMemoryMap.h @@ -69,14 +69,22 @@ class IRMemoryMap // This function can return NULL. ExecutionContextScope *GetBestExecutionContextScope() const; + lldb::TargetSP + GetTarget () + { + return m_target_wp.lock(); + } + protected: // This function should only be used if you know you are using the JIT. // Any other cases should use GetBestExecutionContextScope(). - lldb::ProcessWP GetProcessWP () + + lldb::ProcessWP & + GetProcessWP () { return m_process_wp; } - + private: struct Allocation { diff --git a/include/lldb/Expression/IRToDWARF.h b/include/lldb/Expression/IRToDWARF.h index 43dc99d6d476..a4ae9b7ebfae 100644 --- a/include/lldb/Expression/IRToDWARF.h +++ b/include/lldb/Expression/IRToDWARF.h @@ -11,7 +11,7 @@ #define liblldb_IRToDWARF_h_ #include "llvm/Pass.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "lldb/lldb-public.h" diff --git a/include/lldb/Host/Editline.h b/include/lldb/Host/Editline.h index 9fce193efc9f..697be4cd8e77 100644 --- a/include/lldb/Host/Editline.h +++ b/include/lldb/Host/Editline.h @@ -171,17 +171,13 @@ namespace lldb_private { uint32_t GetCurrentLine(); - /// Hides the current input session in preparation for output - void - Hide(); - - /// Prepare to return to editing after a call to Hide() - void - Refresh(); - /// Interrupt the current edit as if ^C was pressed bool Interrupt(); + + /// Cancel this edit and oblitarate all trace of it + bool + Cancel(); /// Register a callback for the tab key void @@ -207,6 +203,9 @@ namespace lldb_private { bool GetLines (int first_line_number, StringList &lines, bool &interrupted); + void + PrintAsync (Stream *stream, const char *s, size_t len); + private: /// Sets the lowest line number for multi-line editing sessions. A value of zero suppresses @@ -335,7 +334,6 @@ namespace lldb_private { bool m_multiline_enabled = false; std::vector m_input_lines; EditorStatus m_editor_status; - bool m_editor_getting_char = false; bool m_color_prompts = true; int m_terminal_width = 0; int m_base_line_number = 0; @@ -359,6 +357,8 @@ namespace lldb_private { const char * m_fix_indentation_callback_chars = nullptr; CompleteCallbackType m_completion_callback = nullptr; void * m_completion_callback_baton = nullptr; + + Mutex m_output_mutex; }; } diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h index 8219cc06fdc2..5747cb5adcfd 100644 --- a/include/lldb/Host/File.h +++ b/include/lldb/Host/File.h @@ -470,7 +470,7 @@ class File : public IOObject GetPermissions(Error &error) const; static uint32_t - GetPermissions (const char *path, Error &error); + GetPermissions(const FileSpec &file_spec, Error &error); //------------------------------------------------------------------ diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h index 173d948e687b..d0338d41db1b 100644 --- a/include/lldb/Host/FileSpec.h +++ b/include/lldb/Host/FileSpec.h @@ -11,6 +11,8 @@ #define liblldb_FileSpec_h_ #if defined(__cplusplus) +#include + #include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/STLUtils.h" @@ -78,6 +80,12 @@ class FileSpec //------------------------------------------------------------------ explicit FileSpec (const char *path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); + explicit FileSpec (const char *path, bool resolve_path, ArchSpec arch); + + explicit FileSpec(const std::string &path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); + + explicit FileSpec(const std::string &path, bool resolve_path, ArchSpec arch); + //------------------------------------------------------------------ /// Copy constructor /// @@ -259,7 +267,7 @@ class FileSpec /// The stream to which to dump the object description. //------------------------------------------------------------------ void - Dump (Stream *s) const; + Dump(Stream *s) const; //------------------------------------------------------------------ /// Existence test. @@ -359,16 +367,25 @@ class FileSpec IsSourceImplementationFile () const; //------------------------------------------------------------------ - /// Returns true if the filespec represents path that is relative - /// path to the current working directory. + /// Returns true if the filespec represents a relative path. /// /// @return - /// \b true if the filespec represents a current working - /// directory relative path, \b false otherwise. + /// \b true if the filespec represents a relative path, + /// \b false otherwise. //------------------------------------------------------------------ bool - IsRelativeToCurrentWorkingDirectory () const; - + IsRelative() const; + + //------------------------------------------------------------------ + /// Returns true if the filespec represents an absolute path. + /// + /// @return + /// \b true if the filespec represents an absolute path, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + IsAbsolute() const; + TimeValue GetModificationTime () const; @@ -408,6 +425,20 @@ class FileSpec std::string GetPath (bool denormalize = true) const; + const char * + GetCString(bool denormalize = true) const; + + //------------------------------------------------------------------ + /// Extract the full path to the file. + /// + /// Extract the directory and path into an llvm::SmallVectorImpl<> + /// + /// @return + /// Returns a std::string with the directory and filename + /// concatenated. + //------------------------------------------------------------------ + void GetPath(llvm::SmallVectorImpl &path, bool denormalize = true) const; + //------------------------------------------------------------------ /// Extract the extension of the file. /// @@ -530,6 +561,45 @@ class FileSpec lldb::DataBufferSP MemoryMapFileContents (off_t offset = 0, size_t length = SIZE_MAX) const; + + //------------------------------------------------------------------ + /// Memory map part of, or the entire contents of, a file only if + /// the file is local (not on a network mount). + /// + /// Returns a shared pointer to a data buffer that contains all or + /// part of the contents of a file. The data will be memory mapped + /// if the file is local and will lazily page in data from the file + /// as memory is accessed. If the data is memory mapped, the data + /// that is mapped will start \a offset bytes into the file, and + /// \a length bytes will be mapped. If \a length is + /// greater than the number of bytes available in the file starting + /// at \a offset, the number of bytes will be appropriately + /// truncated. The final number of bytes that get mapped can be + /// verified using the DataBuffer::GetByteSize() function on the return + /// shared data pointer object contents. + /// + /// If the file is on a network mount the data will be read into a + /// heap buffer immediately so that accesses to the data won't later + /// cause a crash if we touch a page that isn't paged in and the + /// network mount has been disconnected or gone away. + /// + /// @param[in] offset + /// The offset in bytes from the beginning of the file where + /// memory mapping should begin. + /// + /// @param[in] length + /// The size in bytes that should be mapped starting \a offset + /// bytes into the file. If \a length is \c SIZE_MAX, map + /// as many bytes as possible. + /// + /// @return + /// A shared pointer to the memory mapped data. This shared + /// pointer can contain a NULL DataBuffer pointer, so the contained + /// pointer must be checked prior to using it. + //------------------------------------------------------------------ + lldb::DataBufferSP + MemoryMapFileContentsIfLocal(off_t file_offset, size_t file_size) const; + //------------------------------------------------------------------ /// Read part of, or the entire contents of, a file into a heap based data buffer. /// @@ -579,9 +649,12 @@ class FileSpec lldb::DataBufferSP ReadFileContentsAsCString(Error *error_ptr = NULL); - static void Normalize(llvm::SmallVectorImpl &path, PathSyntax syntax = ePathSyntaxHostNative); - static void DeNormalize(llvm::SmallVectorImpl &path, PathSyntax syntax = ePathSyntaxHostNative); - + //------------------------------------------------------------------ + /// Normalize a pathname by collapsing redundant separators and + /// up-level references. + //------------------------------------------------------------------ + void + NormalizePath (); //------------------------------------------------------------------ /// Run through the input string, replaying the effect of any ".." and produce @@ -613,6 +686,15 @@ class FileSpec void SetFile (const char *path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); + void + SetFile(const char *path, bool resolve_path, ArchSpec arch); + + void + SetFile(const std::string &path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); + + void + SetFile(const std::string &path, bool resolve_path, ArchSpec arch); + bool IsResolved () const { @@ -668,10 +750,25 @@ class FileSpec FileSpec CopyByRemovingLastPathComponent () const; - + void - AppendPathComponent (const char *new_path); - + PrependPathComponent(const char *new_path); + + void + PrependPathComponent(const std::string &new_path); + + void + PrependPathComponent(const FileSpec &new_path); + + void + AppendPathComponent(const char *new_path); + + void + AppendPathComponent(const std::string &new_path); + + void + AppendPathComponent(const FileSpec &new_path); + void RemoveLastPathComponent (); @@ -706,8 +803,7 @@ class FileSpec typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, FileType file_type, - const FileSpec &spec -); + const FileSpec &spec); static EnumerateDirectoryResult EnumerateDirectory (const char *dir_path, @@ -717,6 +813,11 @@ class FileSpec EnumerateDirectoryCallbackType callback, void *callback_baton); + typedef std::function DirectoryCallback; + + static EnumerateDirectoryResult + ForEachItemInDirectory (const char *dir_path, DirectoryCallback const &callback); + protected: //------------------------------------------------------------------ // Member variables diff --git a/include/lldb/Host/FileSystem.h b/include/lldb/Host/FileSystem.h index adcbfc9d590d..bea1ec80172e 100644 --- a/include/lldb/Host/FileSystem.h +++ b/include/lldb/Host/FileSystem.h @@ -24,19 +24,36 @@ class FileSystem public: static FileSpec::PathSyntax GetNativePathSyntax(); - static Error MakeDirectory(const char *path, uint32_t mode); - static Error DeleteDirectory(const char *path, bool recurse); + static Error MakeDirectory(const FileSpec &file_spec, uint32_t mode); + static Error DeleteDirectory(const FileSpec &file_spec, bool recurse); - static Error GetFilePermissions(const char *path, uint32_t &file_permissions); - static Error SetFilePermissions(const char *path, uint32_t file_permissions); + static Error GetFilePermissions(const FileSpec &file_spec, + uint32_t &file_permissions); + static Error SetFilePermissions(const FileSpec &file_spec, + uint32_t file_permissions); static lldb::user_id_t GetFileSize(const FileSpec &file_spec); static bool GetFileExists(const FileSpec &file_spec); - static Error Symlink(const char *src, const char *dst); - static Error Readlink(const char *path, char *buf, size_t buf_len); - static Error Unlink(const char *path); + static Error Hardlink(const FileSpec &src, const FileSpec &dst); + static Error Symlink(const FileSpec &src, const FileSpec &dst); + static Error Readlink(const FileSpec &src, FileSpec &dst); + static Error Unlink(const FileSpec &file_spec); static bool CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high); + static bool CalculateMD5(const FileSpec &file_spec, + uint64_t offset, + uint64_t length, + uint64_t &low, + uint64_t &high); + + static bool CalculateMD5AsString(const FileSpec &file_spec, std::string& digest_str); + static bool CalculateMD5AsString(const FileSpec &file_spec, + uint64_t offset, + uint64_t length, + std::string& digest_str); + + /// Return \b true if \a spec is on a locally mounted file system, \b false otherwise. + static bool IsLocal(const FileSpec &spec); }; } diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h index 9a68c698c826..caf33634057d 100644 --- a/include/lldb/Host/Host.h +++ b/include/lldb/Host/Host.h @@ -133,9 +133,6 @@ class Host static const char * GetSignalAsCString (int signo); - static void - WillTerminate (); - typedef void (*ThreadLocalStorageCleanupCallback) (void *p); static lldb::thread_key_t @@ -236,12 +233,16 @@ class Host GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info); #if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined (__NetBSD__) +#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) + static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info); static Error LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid); static bool AddPosixSpawnFileAction(void *file_actions, const FileAction *info, Log *log, Error &error); -#endif + +#endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__) +#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__) static const lldb_private::UnixSignalsSP& GetUnixSignals (); @@ -249,14 +250,33 @@ class Host static Error LaunchProcess (ProcessLaunchInfo &launch_info); + //------------------------------------------------------------------ + /// Perform expansion of the command-line for this launch info + /// This can potentially involve wildcard expansion + // environment variable replacement, and whatever other + // argument magic the platform defines as part of its typical + // user experience + //------------------------------------------------------------------ static Error - RunShellCommand (const char *command, // Shouldn't be NULL - const char *working_dir, // Pass NULL to use the current working directory - int *status_ptr, // Pass NULL if you don't want the process exit status - int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit - std::string *command_output, // Pass NULL if you don't want the command output - uint32_t timeout_sec, - bool run_in_default_shell = true); + ShellExpandArguments (ProcessLaunchInfo &launch_info); + + static Error + RunShellCommand(const char *command, // Shouldn't be NULL + const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory + int *status_ptr, // Pass NULL if you don't want the process exit status + int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit + std::string *command_output, // Pass NULL if you don't want the command output + uint32_t timeout_sec, + bool run_in_default_shell = true); + + static Error + RunShellCommand(const Args& args, + const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory + int *status_ptr, // Pass NULL if you don't want the process exit status + int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit + std::string *command_output, // Pass NULL if you don't want the command output + uint32_t timeout_sec, + bool run_in_default_shell = true); static lldb::DataBufferSP GetAuxvData (lldb_private::Process *process); @@ -268,9 +288,6 @@ class Host OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no); - static void - Backtrace (Stream &strm, uint32_t max_frames); - static size_t GetEnvironment (StringList &env); }; diff --git a/include/lldb/Host/HostInfo.h b/include/lldb/Host/HostInfo.h index cbbf6cd2d49c..6bb009997896 100644 --- a/include/lldb/Host/HostInfo.h +++ b/include/lldb/Host/HostInfo.h @@ -38,8 +38,13 @@ #include "lldb/Host/windows/HostInfoWindows.h" #define HOST_INFO_TYPE HostInfoWindows #elif defined(__linux__) +#if defined(__ANDROID_NDK__) +#include "lldb/Host/android/HostInfoAndroid.h" +#define HOST_INFO_TYPE HostInfoAndroid +#else #include "lldb/Host/linux/HostInfoLinux.h" #define HOST_INFO_TYPE HostInfoLinux +#endif #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "lldb/Host/freebsd/HostInfoFreeBSD.h" #define HOST_INFO_TYPE HostInfoFreeBSD diff --git a/include/lldb/Host/HostInfoBase.h b/include/lldb/Host/HostInfoBase.h index 5a8a06329500..6a5f784ebba3 100644 --- a/include/lldb/Host/HostInfoBase.h +++ b/include/lldb/Host/HostInfoBase.h @@ -115,7 +115,9 @@ class HostInfoBase protected: static bool ComputeSharedLibraryDirectory(FileSpec &file_spec); static bool ComputeSupportExeDirectory(FileSpec &file_spec); - static bool ComputeTempFileDirectory(FileSpec &file_spec); + static bool ComputeProcessTempFileDirectory(FileSpec &file_spec); + static bool ComputeGlobalTempFileDirectory(FileSpec &file_spec); + static bool ComputeTempFileBaseDirectory(FileSpec &file_spec); static bool ComputeHeaderDirectory(FileSpec &file_spec); static bool ComputeSystemPluginsDirectory(FileSpec &file_spec); static bool ComputeClangDirectory(FileSpec &file_spec); diff --git a/include/lldb/Host/LockFile.h b/include/lldb/Host/LockFile.h new file mode 100644 index 000000000000..a89560481874 --- /dev/null +++ b/include/lldb/Host/LockFile.h @@ -0,0 +1,27 @@ +//===-- LockFile.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_LockFile_h_ +#define liblldb_Host_LockFile_h_ + +#if defined(_WIN32) +#include "lldb/Host/windows/LockFileWindows.h" +namespace lldb_private +{ +typedef LockFileWindows LockFile; +} +#else +#include "lldb/Host/posix/LockFilePosix.h" +namespace lldb_private +{ +typedef LockFilePosix LockFile; +} +#endif + +#endif // liblldb_Host_LockFile_h_ diff --git a/include/lldb/Host/LockFileBase.h b/include/lldb/Host/LockFileBase.h new file mode 100644 index 000000000000..35dd7d817c59 --- /dev/null +++ b/include/lldb/Host/LockFileBase.h @@ -0,0 +1,73 @@ +//===-- LockFileBase.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_LockFileBase_h_ +#define liblldb_Host_LockFileBase_h_ + +#include "lldb/Core/Error.h" + +#include + +namespace lldb_private +{ + +class LockFileBase +{ +public: + virtual ~LockFileBase () = default; + + bool + IsLocked () const; + + Error + WriteLock (const uint64_t start, const uint64_t len); + Error + TryWriteLock (const uint64_t start, const uint64_t len); + + Error + ReadLock (const uint64_t start, const uint64_t len); + Error + TryReadLock (const uint64_t start, const uint64_t len); + + Error + Unlock (); + +protected: + using Locker = std::function; + + LockFileBase (int fd); + + virtual bool + IsValidFile () const; + + virtual Error + DoWriteLock (const uint64_t start, const uint64_t len) = 0; + virtual Error + DoTryWriteLock (const uint64_t start, const uint64_t len) = 0; + + virtual Error + DoReadLock (const uint64_t start, const uint64_t len) = 0; + virtual Error + DoTryReadLock (const uint64_t start, const uint64_t len) = 0; + + virtual Error + DoUnlock () = 0; + + Error + DoLock (const Locker &locker, const uint64_t start, const uint64_t len); + + int m_fd; // not owned. + bool m_locked; + uint64_t m_start; + uint64_t m_len; +}; + +} + +#endif diff --git a/include/lldb/Host/PipeBase.h b/include/lldb/Host/PipeBase.h index 5ef2bb530281..8680a252d8b6 100644 --- a/include/lldb/Host/PipeBase.h +++ b/include/lldb/Host/PipeBase.h @@ -40,6 +40,8 @@ class PipeBase virtual int GetWriteFileDescriptor() const = 0; virtual int ReleaseReadFileDescriptor() = 0; virtual int ReleaseWriteFileDescriptor() = 0; + virtual void CloseReadFileDescriptor() = 0; + virtual void CloseWriteFileDescriptor() = 0; // Close both descriptors virtual void Close() = 0; diff --git a/include/lldb/Host/Socket.h b/include/lldb/Host/Socket.h index ee85f85fcaf2..f4599b5ab87b 100644 --- a/include/lldb/Host/Socket.h +++ b/include/lldb/Host/Socket.h @@ -56,7 +56,12 @@ class Socket : public IOObject // Initialize a Tcp Socket object in listening mode. listen and accept are implemented // separately because the caller may wish to manipulate or query the socket after it is // initialized, but before entering a blocking accept. - static Error TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket, Predicate* predicate); + static Error TcpListen( + llvm::StringRef host_and_port, + bool child_processes_inherit, + Socket *&socket, + Predicate* predicate, + int backlog = 5); static Error TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket); static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); diff --git a/include/lldb/Host/Time.h b/include/lldb/Host/Time.h new file mode 100644 index 000000000000..1481d381053d --- /dev/null +++ b/include/lldb/Host/Time.h @@ -0,0 +1,26 @@ +//===-- Time.h --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Include system time headers, adding missing functions as necessary + +#ifndef liblldb_Host_Time_h_ +#define liblldb_Host_Time_h_ + +#ifdef __ANDROID_NDK__ +#include +#endif + +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 +#include +extern time_t timegm(struct tm* t); +#else +#include +#endif + +#endif // liblldb_Host_Time_h_ diff --git a/include/lldb/Host/XML.h b/include/lldb/Host/XML.h new file mode 100644 index 000000000000..e3547d834635 --- /dev/null +++ b/include/lldb/Host/XML.h @@ -0,0 +1,234 @@ +//===-- XML.h ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_XML_h_ +#define liblldb_XML_h_ + +// C Includes + +#if defined( LIBXML2_DEFINED ) +#include +#endif + +// C++ Includes + +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "llvm/ADT/StringRef.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/StructuredData.h" + + +namespace lldb_private { + +#if defined( LIBXML2_DEFINED ) + typedef xmlNodePtr XMLNodeImpl; + typedef xmlDocPtr XMLDocumentImpl; +#else + typedef void * XMLNodeImpl; + typedef void * XMLDocumentImpl; +#endif + + class XMLNode; + + typedef std::vector NamePath; + typedef std::function NodeCallback; + typedef std::function AttributeCallback; + + class XMLNode + { + public: + XMLNode(); + + XMLNode(XMLNodeImpl node); + + ~XMLNode(); + + explicit operator bool() const + { + return IsValid(); + } + + void + Clear(); + + bool + IsValid() const; + + bool + IsElement () const; + + llvm::StringRef + GetName() const; + + bool + GetElementText (std::string &text) const; + + bool + GetElementTextAsUnsigned (uint64_t &value, uint64_t fail_value = 0, int base = 0) const; + + bool + GetElementTextAsFloat (double &value, double fail_value = 0.0) const; + + bool + NameIs (const char *name) const; + + XMLNode + GetParent() const; + + XMLNode + GetSibling() const; + + XMLNode + GetChild () const; + + llvm::StringRef + GetAttributeValue(const char *name, const char *fail_value = NULL) const; + + XMLNode + FindFirstChildElementWithName (const char *name) const; + + XMLNode + GetElementForPath (const NamePath &path); + + //---------------------------------------------------------------------- + // Iterate through all sibling nodes of any type + //---------------------------------------------------------------------- + void + ForEachSiblingNode (NodeCallback const &callback) const; + + //---------------------------------------------------------------------- + // Iterate through only the sibling nodes that are elements + //---------------------------------------------------------------------- + void + ForEachSiblingElement (NodeCallback const &callback) const; + + //---------------------------------------------------------------------- + // Iterate through only the sibling nodes that are elements and whose + // name matches \a name. + //---------------------------------------------------------------------- + void + ForEachSiblingElementWithName (const char *name, NodeCallback const &callback) const; + + void + ForEachChildNode (NodeCallback const &callback) const; + + void + ForEachChildElement (NodeCallback const &callback) const; + + void + ForEachChildElementWithName (const char *name, NodeCallback const &callback) const; + + void + ForEachAttribute (AttributeCallback const &callback) const; + + protected: + XMLNodeImpl m_node; + }; + + class XMLDocument + { + public: + + XMLDocument (); + + ~XMLDocument (); + + explicit operator bool() const + { + return IsValid(); + } + + bool + IsValid() const; + + void + Clear(); + + bool + ParseFile (const char *path); + + bool + ParseMemory (const char *xml, size_t xml_length, const char *url = "untitled.xml"); + + //---------------------------------------------------------------------- + // If \a name is NULL, just get the root element node, else only return + // a value XMLNode if the name of the root element matches \a name. + //---------------------------------------------------------------------- + XMLNode + GetRootElement(const char *required_name = nullptr); + + const std::string & + GetErrors() const; + + static void + ErrorCallback (void *ctx, const char *format, ...); + + static bool + XMLEnabled (); + + protected: + XMLDocumentImpl m_document; + StreamString m_errors; + }; + + class ApplePropertyList + { + public: + ApplePropertyList(); + + ApplePropertyList(const char *path); + + ~ApplePropertyList(); + + bool + ParseFile (const char *path); + + const std::string & + GetErrors() const; + + explicit operator bool() const + { + return IsValid(); + } + + bool + IsValid() const; + + XMLNode + GetValueNode (const char *key) const; + + bool + GetValueAsString (const char *key, std::string &value) const; + + StructuredData::ObjectSP + GetStructuredData(); + + protected: + + // Using a node returned from GetValueNode() extract its value as a + // string (if possible). Array and dictionary nodes will return false + // as they have no string value. Boolean nodes will return true and + // \a value will be "true" or "false" as the string value comes from + // the element name itself. All other nodes will return the text + // content of the XMLNode. + static bool + ExtractStringFromValueNode (const XMLNode &node, std::string &value); + + XMLDocument m_xml_doc; + XMLNode m_dict_node; + }; +} // namespace lldb_private + +#endif // liblldb_XML_h_ diff --git a/include/lldb/Host/common/NativeBreakpointList.h b/include/lldb/Host/common/NativeBreakpointList.h index 51617330d075..aba2f8a74cdc 100644 --- a/include/lldb/Host/common/NativeBreakpointList.h +++ b/include/lldb/Host/common/NativeBreakpointList.h @@ -42,6 +42,9 @@ namespace lldb_private Error GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp); + Error + RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const; + private: typedef std::map BreakpointMap; diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h index 83c14a5ab37a..f6a685aae147 100644 --- a/include/lldb/Host/common/NativeProcessProtocol.h +++ b/include/lldb/Host/common/NativeProcessProtocol.h @@ -16,6 +16,7 @@ #include "lldb/lldb-types.h" #include "lldb/Core/Error.h" #include "lldb/Host/Mutex.h" +#include "llvm/ADT/StringRef.h" #include "NativeBreakpointList.h" #include "NativeWatchpointList.h" @@ -90,13 +91,16 @@ namespace lldb_private GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info); virtual Error - ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0; + ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) = 0; virtual Error - WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0; + ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) = 0; virtual Error - AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0; + WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) = 0; + + virtual Error + AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) = 0; virtual Error DeallocateMemory (lldb::addr_t addr) = 0; @@ -283,6 +287,16 @@ namespace lldb_private bool UnregisterNativeDelegate (NativeDelegate &native_delegate); + // Called before termination of NativeProcessProtocol's instance. + virtual void + Terminate (); + + virtual Error + GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) = 0; + + virtual Error + GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) = 0; + protected: lldb::pid_t m_pid; diff --git a/include/lldb/Host/common/NativeRegisterContext.h b/include/lldb/Host/common/NativeRegisterContext.h index e9c03e3c20a4..098f148f95d0 100644 --- a/include/lldb/Host/common/NativeRegisterContext.h +++ b/include/lldb/Host/common/NativeRegisterContext.h @@ -99,14 +99,26 @@ class NativeRegisterContext: virtual Error ClearAllHardwareWatchpoints (); + virtual Error + IsWatchpointHit(uint32_t wp_index, bool &is_hit); + + virtual Error + GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr); + + virtual Error + IsWatchpointVacant (uint32_t wp_index, bool &is_vacant); + + virtual lldb::addr_t + GetWatchpointAddress (uint32_t wp_index); + virtual bool HardwareSingleStep (bool enable); virtual Error - ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, lldb::addr_t src_len, RegisterValue ®_value); + ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, size_t src_len, RegisterValue ®_value); virtual Error - WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, lldb::addr_t dst_len, const RegisterValue ®_value); + WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, size_t dst_len, const RegisterValue ®_value); //------------------------------------------------------------------ // Subclasses should not override these @@ -129,6 +141,9 @@ class NativeRegisterContext: lldb::addr_t GetPC (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + virtual lldb::addr_t + GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS); + Error SetPC (lldb::addr_t pc); diff --git a/include/lldb/Host/common/SoftwareBreakpoint.h b/include/lldb/Host/common/SoftwareBreakpoint.h index 1fed19eca612..83b3d18aa768 100644 --- a/include/lldb/Host/common/SoftwareBreakpoint.h +++ b/include/lldb/Host/common/SoftwareBreakpoint.h @@ -17,6 +17,8 @@ namespace lldb_private { class SoftwareBreakpoint : public NativeBreakpoint { + friend class NativeBreakpointList; + public: static Error CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_spn); diff --git a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h index 660b9d169bfc..bcbb6014b116 100644 --- a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -38,23 +38,25 @@ class ConnectionFileDescriptor : public Connection ConnectionFileDescriptor(int fd, bool owns_fd); + ConnectionFileDescriptor(Socket* socket); + virtual ~ConnectionFileDescriptor(); - virtual bool IsConnected() const; + bool IsConnected() const override; - virtual lldb::ConnectionStatus Connect(const char *s, Error *error_ptr); + lldb::ConnectionStatus Connect(const char *s, Error *error_ptr) override; - virtual lldb::ConnectionStatus Disconnect(Error *error_ptr); + lldb::ConnectionStatus Disconnect(Error *error_ptr) override; - virtual size_t Read(void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr); + size_t Read(void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr) override; - virtual size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr) override; - virtual std::string GetURI(); + std::string GetURI() override; lldb::ConnectionStatus BytesAvailable(uint32_t timeout_usec, Error *error_ptr); - bool InterruptRead(); + bool InterruptRead() override; lldb::IOObjectSP GetReadObject() @@ -104,6 +106,8 @@ class ConnectionFileDescriptor : public Connection std::string m_uri; private: + void InitializeSocket(Socket* socket); + DISALLOW_COPY_AND_ASSIGN(ConnectionFileDescriptor); }; diff --git a/include/lldb/Host/posix/Fcntl.h b/include/lldb/Host/posix/Fcntl.h new file mode 100644 index 000000000000..3e3a472f0a20 --- /dev/null +++ b/include/lldb/Host/posix/Fcntl.h @@ -0,0 +1,25 @@ +//===-- Fcntl.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This file defines fcntl functions & structures + +#ifndef liblldb_Host_posix_Fcntl_h_ +#define liblldb_Host_posix_Fcntl_h_ + +#ifdef __ANDROID_NDK__ +#include +#endif + +#include + +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 +#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6) +#endif + +#endif // liblldb_Host_posix_Fcntl_h_ diff --git a/include/lldb/Host/posix/HostProcessPosix.h b/include/lldb/Host/posix/HostProcessPosix.h index 8c1b0599e114..c9534991361b 100644 --- a/include/lldb/Host/posix/HostProcessPosix.h +++ b/include/lldb/Host/posix/HostProcessPosix.h @@ -29,13 +29,13 @@ class HostProcessPosix : public HostNativeProcessBase virtual Error Signal(int signo) const; static Error Signal(lldb::process_t process, int signo); - virtual Error Terminate(); - virtual Error GetMainModule(FileSpec &file_spec) const; + Error Terminate() override; + Error GetMainModule(FileSpec &file_spec) const override; - virtual lldb::pid_t GetProcessId() const; - virtual bool IsRunning() const; + lldb::pid_t GetProcessId() const override; + bool IsRunning() const override; - virtual HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals); + HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) override; }; } diff --git a/include/lldb/Host/posix/HostThreadPosix.h b/include/lldb/Host/posix/HostThreadPosix.h index e0eaedf73be2..8839b8d4068b 100644 --- a/include/lldb/Host/posix/HostThreadPosix.h +++ b/include/lldb/Host/posix/HostThreadPosix.h @@ -24,8 +24,8 @@ class HostThreadPosix : public HostNativeThreadBase HostThreadPosix(lldb::thread_t thread); virtual ~HostThreadPosix(); - virtual Error Join(lldb::thread_result_t *result); - virtual Error Cancel(); + Error Join(lldb::thread_result_t *result) override; + Error Cancel() override; Error Detach(); }; diff --git a/include/lldb/Host/posix/LockFilePosix.h b/include/lldb/Host/posix/LockFilePosix.h new file mode 100644 index 000000000000..999397ec2bb5 --- /dev/null +++ b/include/lldb/Host/posix/LockFilePosix.h @@ -0,0 +1,42 @@ +//===-- LockFilePosix.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_posix_LockFilePosix_h_ +#define liblldb_Host_posix_LockFilePosix_h_ + +#include "lldb/Host/LockFileBase.h" + +namespace lldb_private { + +class LockFilePosix : public LockFileBase +{ +public: + explicit LockFilePosix (int fd); + ~LockFilePosix (); + +protected: + Error + DoWriteLock (const uint64_t start, const uint64_t len) override; + + Error + DoTryWriteLock (const uint64_t start, const uint64_t len) override; + + Error + DoReadLock (const uint64_t start, const uint64_t len) override; + + Error + DoTryReadLock (const uint64_t start, const uint64_t len) override; + + Error + DoUnlock () override; +}; + +} // namespace lldb_private + +#endif // liblldb_Host_posix_LockFilePosix_h_ diff --git a/include/lldb/Host/posix/PipePosix.h b/include/lldb/Host/posix/PipePosix.h index fbdac66149d6..710b77d34bdc 100644 --- a/include/lldb/Host/posix/PipePosix.h +++ b/include/lldb/Host/posix/PipePosix.h @@ -16,7 +16,7 @@ namespace lldb_private { //---------------------------------------------------------------------- -/// @class PipePosix PipePosix .h "lldb/Host/posix/PipePosix.h" +/// @class PipePosix PipePosix.h "lldb/Host/posix/PipePosix.h" /// @brief A posix-based implementation of Pipe, a class that abtracts /// unix style pipes. /// @@ -28,6 +28,11 @@ class PipePosix : public PipeBase static int kInvalidDescriptor; PipePosix(); + PipePosix(int read_fd, int write_fd); + PipePosix(const PipePosix &) = delete; + PipePosix(PipePosix &&pipe_posix); + PipePosix &operator=(const PipePosix &) = delete; + PipePosix &operator=(PipePosix &&pipe_posix); ~PipePosix() override; @@ -55,6 +60,11 @@ class PipePosix : public PipeBase ReleaseReadFileDescriptor() override; int ReleaseWriteFileDescriptor() override; + void + CloseReadFileDescriptor() override; + void + CloseWriteFileDescriptor() override; + // Close both descriptors void @@ -69,11 +79,6 @@ class PipePosix : public PipeBase ReadWithTimeout(void *buf, size_t size, const std::chrono::microseconds &timeout, size_t &bytes_read) override; private: - void - CloseReadFileDescriptor(); - void - CloseWriteFileDescriptor(); - int m_fds[2]; }; diff --git a/include/lldb/Host/posix/ProcessLauncherPosix.h b/include/lldb/Host/posix/ProcessLauncherPosix.h index c0e2a36e4e5e..a5e57ccb26ed 100644 --- a/include/lldb/Host/posix/ProcessLauncherPosix.h +++ b/include/lldb/Host/posix/ProcessLauncherPosix.h @@ -18,7 +18,7 @@ namespace lldb_private class ProcessLauncherPosix : public ProcessLauncher { public: - virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error); + HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) override; }; } diff --git a/include/lldb/Initialization/SystemInitializer.h b/include/lldb/Initialization/SystemInitializer.h new file mode 100644 index 000000000000..c7f98f24ae48 --- /dev/null +++ b/include/lldb/Initialization/SystemInitializer.h @@ -0,0 +1,26 @@ +//===-- SystemInitializer.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INITIALIZATION_SYSTEM_INITIALIZER_H +#define LLDB_INITIALIZATION_SYSTEM_INITIALIZER_H + +namespace lldb_private +{ +class SystemInitializer +{ + public: + SystemInitializer(); + virtual ~SystemInitializer(); + + virtual void Initialize() = 0; + virtual void Terminate() = 0; +}; +} + +#endif diff --git a/include/lldb/Initialization/SystemInitializerCommon.h b/include/lldb/Initialization/SystemInitializerCommon.h new file mode 100644 index 000000000000..af66c93a5e48 --- /dev/null +++ b/include/lldb/Initialization/SystemInitializerCommon.h @@ -0,0 +1,38 @@ +//===-- SystemInitializerCommon.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INITIALIZATION_SYSTEM_INITIALIZER_COMMON_H +#define LLDB_INITIALIZATION_SYSTEM_INITIALIZER_COMMON_H + +#include "SystemInitializer.h" + +namespace lldb_private +{ +//------------------------------------------------------------------ +/// Initializes common lldb functionality. +/// +/// This class is responsible for initializing a subset of lldb +/// useful to both debug servers and debug clients. Debug servers +/// do not use all of LLDB and desire small binary sizes, so this +/// functionality is separate. This class is used by constructing +/// an instance of SystemLifetimeManager with this class passed to +/// the constructor. +//------------------------------------------------------------------ +class SystemInitializerCommon : public SystemInitializer +{ + public: + SystemInitializerCommon(); + virtual ~SystemInitializerCommon(); + + void Initialize() override; + void Terminate() override; +}; +} + +#endif diff --git a/include/lldb/Initialization/SystemLifetimeManager.h b/include/lldb/Initialization/SystemLifetimeManager.h new file mode 100644 index 000000000000..843ec2820677 --- /dev/null +++ b/include/lldb/Initialization/SystemLifetimeManager.h @@ -0,0 +1,42 @@ +//===-- SystemLifetimeManager.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INITIALIZATION_SYSTEM_LIFETIME_MANAGER_H +#define LLDB_INITIALIZATION_SYSTEM_LIFETIME_MANAGER_H + +#include "lldb/lldb-private-types.h" +#include "lldb/Host/Mutex.h" + +#include + +namespace lldb_private +{ +class SystemInitializer; + +class SystemLifetimeManager +{ + public: + SystemLifetimeManager(); + ~SystemLifetimeManager(); + + void Initialize(std::unique_ptr initializer, LoadPluginCallbackType plugin_callback); + void Terminate(); + + private: + Mutex m_mutex; + std::unique_ptr m_initializer; + bool m_initialized; + + // Noncopyable. + SystemLifetimeManager(const SystemLifetimeManager &other) = delete; + SystemLifetimeManager &operator=(const SystemLifetimeManager &other) = delete; +}; +} + +#endif diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h index fe29df468de7..e11636b63f17 100644 --- a/include/lldb/Interpreter/Args.h +++ b/include/lldb/Interpreter/Args.h @@ -18,6 +18,7 @@ #include // Other libraries and framework includes +#include "llvm/ADT/StringRef.h" // Project includes #include "lldb/lldb-private-types.h" #include "lldb/lldb-types.h" @@ -75,11 +76,9 @@ class Args /// A NULL terminated command that will be copied and split up /// into arguments. /// - /// @see Args::SetCommandString(const char *) + /// @see Args::SetCommandString(llvm::StringRef) //------------------------------------------------------------------ - Args (const char *command = NULL); - - Args (const char *command, size_t len); + Args (llvm::StringRef command = llvm::StringRef()); Args (const Args &rhs); @@ -108,7 +107,7 @@ class Args /// that can be accessed via the accessor functions. /// /// @param[in] command - /// A NULL terminated command that will be copied and split up + /// A command StringRef that will be copied and split up /// into arguments. /// /// @see Args::GetArgumentCount() const @@ -118,10 +117,7 @@ class Args /// @see Args::Unshift (const char *) //------------------------------------------------------------------ void - SetCommandString (const char *command); - - void - SetCommandString (const char *command, size_t len); + SetCommandString (llvm::StringRef command); bool GetCommandString (std::string &command) const; @@ -449,6 +445,9 @@ class Args void UpdateArgvFromArgs (); + + llvm::StringRef + ParseSingleArgument (llvm::StringRef command); }; } // namespace lldb_private diff --git a/include/lldb/Interpreter/CommandInterpreter.h b/include/lldb/Interpreter/CommandInterpreter.h index 20b6ff95be8b..1962050dffcb 100644 --- a/include/lldb/Interpreter/CommandInterpreter.h +++ b/include/lldb/Interpreter/CommandInterpreter.h @@ -625,6 +625,12 @@ class CommandInterpreter : bool GetPromptOnQuit () const; + void + SetPromptOnQuit (bool b); + + void + ResolveCommand(const char *command_line, CommandReturnObject &result); + bool GetStopCmdSourceOnError () const; @@ -685,6 +691,13 @@ class CommandInterpreter : Error PreprocessCommand (std::string &command); + // Completely resolves aliases and abbreviations, returning a pointer to the + // final command object and updating command_line to the fully substituted + // and translated command. + CommandObject * + ResolveCommandImpl(std::string &command_line, CommandReturnObject &result); + + Debugger &m_debugger; // The debugger session that this interpreter is associated with ExecutionContextRef m_exe_ctx_ref; // The current execution context to use when handling commands bool m_synchronous_execution; diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h index bace3264dafa..c0901d5e3032 100644 --- a/include/lldb/Interpreter/CommandObject.h +++ b/include/lldb/Interpreter/CommandObject.h @@ -98,7 +98,7 @@ class CommandObject return m_interpreter; } - const char * + virtual const char * GetHelp (); virtual const char * @@ -113,6 +113,9 @@ class CommandObject void SetHelp (const char * str); + void + SetHelp (std::string str); + void SetHelpLong (const char * str); @@ -192,7 +195,7 @@ class CommandObject static lldb::CommandArgumentType LookupArgumentName (const char *arg_name); - static ArgumentTableEntry * + static const ArgumentTableEntry * FindArgumentDataByType (lldb::CommandArgumentType arg_type); int @@ -217,89 +220,6 @@ class CommandObject bool IsPairType (ArgumentRepetitionType arg_repeat_type); - - enum - { - //---------------------------------------------------------------------- - // eFlagRequiresTarget - // - // Ensures a valid target is contained in m_exe_ctx prior to executing - // the command. If a target doesn't exist or is invalid, the command - // will fail and CommandObject::GetInvalidTargetDescription() will be - // returned as the error. CommandObject subclasses can override the - // virtual function for GetInvalidTargetDescription() to provide custom - // strings when needed. - //---------------------------------------------------------------------- - eFlagRequiresTarget = (1u << 0), - //---------------------------------------------------------------------- - // eFlagRequiresProcess - // - // Ensures a valid process is contained in m_exe_ctx prior to executing - // the command. If a process doesn't exist or is invalid, the command - // will fail and CommandObject::GetInvalidProcessDescription() will be - // returned as the error. CommandObject subclasses can override the - // virtual function for GetInvalidProcessDescription() to provide custom - // strings when needed. - //---------------------------------------------------------------------- - eFlagRequiresProcess = (1u << 1), - //---------------------------------------------------------------------- - // eFlagRequiresThread - // - // Ensures a valid thread is contained in m_exe_ctx prior to executing - // the command. If a thread doesn't exist or is invalid, the command - // will fail and CommandObject::GetInvalidThreadDescription() will be - // returned as the error. CommandObject subclasses can override the - // virtual function for GetInvalidThreadDescription() to provide custom - // strings when needed. - //---------------------------------------------------------------------- - eFlagRequiresThread = (1u << 2), - //---------------------------------------------------------------------- - // eFlagRequiresFrame - // - // Ensures a valid frame is contained in m_exe_ctx prior to executing - // the command. If a frame doesn't exist or is invalid, the command - // will fail and CommandObject::GetInvalidFrameDescription() will be - // returned as the error. CommandObject subclasses can override the - // virtual function for GetInvalidFrameDescription() to provide custom - // strings when needed. - //---------------------------------------------------------------------- - eFlagRequiresFrame = (1u << 3), - //---------------------------------------------------------------------- - // eFlagRequiresRegContext - // - // Ensures a valid register context (from the selected frame if there - // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) - // is available from m_exe_ctx prior to executing the command. If a - // target doesn't exist or is invalid, the command will fail and - // CommandObject::GetInvalidRegContextDescription() will be returned as - // the error. CommandObject subclasses can override the virtual function - // for GetInvalidRegContextDescription() to provide custom strings when - // needed. - //---------------------------------------------------------------------- - eFlagRequiresRegContext = (1u << 4), - //---------------------------------------------------------------------- - // eFlagTryTargetAPILock - // - // Attempts to acquire the target lock if a target is selected in the - // command interpreter. If the command object fails to acquire the API - // lock, the command will fail with an appropriate error message. - //---------------------------------------------------------------------- - eFlagTryTargetAPILock = (1u << 5), - //---------------------------------------------------------------------- - // eFlagProcessMustBeLaunched - // - // Verifies that there is a launched process in m_exe_ctx, if there - // isn't, the command will fail with an appropriate error message. - //---------------------------------------------------------------------- - eFlagProcessMustBeLaunched = (1u << 6), - //---------------------------------------------------------------------- - // eFlagProcessMustBePaused - // - // Verifies that there is a paused process in m_exe_ctx, if there - // isn't, the command will fail with an appropriate error message. - //---------------------------------------------------------------------- - eFlagProcessMustBePaused = (1u << 7) - }; bool ParseOptions (Args& args, CommandReturnObject &result); diff --git a/include/lldb/Interpreter/OptionValue.h b/include/lldb/Interpreter/OptionValue.h index 787430a96ef5..fd751f744de6 100644 --- a/include/lldb/Interpreter/OptionValue.h +++ b/include/lldb/Interpreter/OptionValue.h @@ -40,6 +40,7 @@ namespace lldb_private { eTypeFileSpec, eTypeFileSpecList, eTypeFormat, + eTypeLanguage, eTypePathMap, eTypeProperties, eTypeRegex, @@ -106,7 +107,7 @@ namespace lldb_private { DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) = 0; virtual Error - SetValueFromCString (const char *value, VarSetOperationType op = eVarSetOperationAssign); + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool Clear () = 0; @@ -187,6 +188,7 @@ namespace lldb_private { case 1u << eTypeFileSpec: return eTypeFileSpec; case 1u << eTypeFileSpecList: return eTypeFileSpecList; case 1u << eTypeFormat: return eTypeFormat; + case 1u << eTypeLanguage: return eTypeLanguage; case 1u << eTypePathMap: return eTypePathMap; case 1u << eTypeProperties: return eTypeProperties; case 1u << eTypeRegex: return eTypeRegex; @@ -270,6 +272,12 @@ namespace lldb_private { const OptionValueFormat * GetAsFormat () const; + OptionValueLanguage * + GetAsLanguage (); + + const OptionValueLanguage * + GetAsLanguage () const; + OptionValuePathMappings * GetAsPathMappings (); @@ -348,6 +356,12 @@ namespace lldb_private { bool SetFormatValue (lldb::Format new_value); + + lldb::LanguageType + GetLanguageValue (lldb::LanguageType fail_value = lldb::eLanguageTypeUnknown) const; + + bool + SetLanguageValue (lldb::LanguageType new_language); const FormatEntity::Entry * GetFormatEntity () const; diff --git a/include/lldb/Interpreter/OptionValueArch.h b/include/lldb/Interpreter/OptionValueArch.h index 662e1ec9f627..3d5d72619efc 100644 --- a/include/lldb/Interpreter/OptionValueArch.h +++ b/include/lldb/Interpreter/OptionValueArch.h @@ -71,7 +71,7 @@ class OptionValueArch : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueArray.h b/include/lldb/Interpreter/OptionValueArray.h index 39ae2f6f43d6..2e44f9f07438 100644 --- a/include/lldb/Interpreter/OptionValueArray.h +++ b/include/lldb/Interpreter/OptionValueArray.h @@ -49,7 +49,7 @@ class OptionValueArray : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueBoolean.h b/include/lldb/Interpreter/OptionValueBoolean.h index e024f3a0f3db..214fd1649d39 100644 --- a/include/lldb/Interpreter/OptionValueBoolean.h +++ b/include/lldb/Interpreter/OptionValueBoolean.h @@ -54,7 +54,7 @@ class OptionValueBoolean : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueChar.h b/include/lldb/Interpreter/OptionValueChar.h index 55f4b63538ea..8fc02093e3d9 100644 --- a/include/lldb/Interpreter/OptionValueChar.h +++ b/include/lldb/Interpreter/OptionValueChar.h @@ -54,7 +54,7 @@ class OptionValueChar : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueDictionary.h b/include/lldb/Interpreter/OptionValueDictionary.h index 5fb698b9f221..efa15dd6ef88 100644 --- a/include/lldb/Interpreter/OptionValueDictionary.h +++ b/include/lldb/Interpreter/OptionValueDictionary.h @@ -50,7 +50,7 @@ class OptionValueDictionary : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueEnumeration.h b/include/lldb/Interpreter/OptionValueEnumeration.h index 68beddfce0d0..e820729385de 100644 --- a/include/lldb/Interpreter/OptionValueEnumeration.h +++ b/include/lldb/Interpreter/OptionValueEnumeration.h @@ -55,7 +55,7 @@ class OptionValueEnumeration : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueFileSpec.h b/include/lldb/Interpreter/OptionValueFileSpec.h index 7e74b605660c..80dd77ecef2a 100644 --- a/include/lldb/Interpreter/OptionValueFileSpec.h +++ b/include/lldb/Interpreter/OptionValueFileSpec.h @@ -22,12 +22,14 @@ namespace lldb_private { class OptionValueFileSpec : public OptionValue { public: - OptionValueFileSpec (); + OptionValueFileSpec (bool resolve = true); - OptionValueFileSpec (const FileSpec &value); + OptionValueFileSpec (const FileSpec &value, + bool resolve = true); OptionValueFileSpec (const FileSpec ¤t_value, - const FileSpec &default_value); + const FileSpec &default_value, + bool resolve = true); virtual ~OptionValueFileSpec() @@ -48,7 +50,7 @@ class OptionValueFileSpec : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool @@ -57,6 +59,7 @@ class OptionValueFileSpec : public OptionValue m_current_value = m_default_value; m_value_was_set = false; m_data_sp.reset(); + m_data_mod_time.Clear(); return true; } @@ -121,7 +124,9 @@ class OptionValueFileSpec : public OptionValue FileSpec m_current_value; FileSpec m_default_value; lldb::DataBufferSP m_data_sp; + TimeValue m_data_mod_time; uint32_t m_completion_mask; + bool m_resolve; }; } // namespace lldb_private diff --git a/include/lldb/Interpreter/OptionValueFileSpecList.h b/include/lldb/Interpreter/OptionValueFileSpecList.h index 792de4e23af6..a105d22e45f9 100644 --- a/include/lldb/Interpreter/OptionValueFileSpecList.h +++ b/include/lldb/Interpreter/OptionValueFileSpecList.h @@ -54,7 +54,7 @@ class OptionValueFileSpecList : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueFormat.h b/include/lldb/Interpreter/OptionValueFormat.h index 245b2eeb5af1..06ed12854318 100644 --- a/include/lldb/Interpreter/OptionValueFormat.h +++ b/include/lldb/Interpreter/OptionValueFormat.h @@ -55,7 +55,7 @@ class OptionValueFormat : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueFormatEntity.h b/include/lldb/Interpreter/OptionValueFormatEntity.h index cc988998bda0..18ace3a6a1b6 100644 --- a/include/lldb/Interpreter/OptionValueFormatEntity.h +++ b/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -43,7 +43,7 @@ class OptionValueFormatEntity : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; bool diff --git a/include/lldb/Interpreter/OptionValueLanguage.h b/include/lldb/Interpreter/OptionValueLanguage.h new file mode 100644 index 000000000000..fba5e22821e0 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueLanguage.h @@ -0,0 +1,107 @@ +//===-- OptionValueLanguage.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_OptionValueLanguage_h_ +#define liblldb_OptionValueLanguage_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-enumerations.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueLanguage : public OptionValue +{ +public: + OptionValueLanguage (lldb::LanguageType value) : + OptionValue(), + m_current_value (value), + m_default_value (value) + { + } + + OptionValueLanguage (lldb::LanguageType current_value, + lldb::LanguageType default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value) + { + } + + virtual + ~OptionValueLanguage () + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + OptionValue::Type + GetType () const override + { + return eTypeLanguage; + } + + void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + + Error + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; + + bool + Clear () override + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + lldb::OptionValueSP + DeepCopy () const override; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + lldb::LanguageType + GetCurrentValue() const + { + return m_current_value; + } + + lldb::LanguageType + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (lldb::LanguageType value) + { + m_current_value = value; + } + + void + SetDefaultValue (lldb::LanguageType value) + { + m_default_value = value; + } + +protected: + lldb::LanguageType m_current_value; + lldb::LanguageType m_default_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueLanguage_h_ diff --git a/include/lldb/Interpreter/OptionValuePathMappings.h b/include/lldb/Interpreter/OptionValuePathMappings.h index 7ebf4947c6af..7b476a9cd366 100644 --- a/include/lldb/Interpreter/OptionValuePathMappings.h +++ b/include/lldb/Interpreter/OptionValuePathMappings.h @@ -48,7 +48,7 @@ class OptionValuePathMappings : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueProperties.h b/include/lldb/Interpreter/OptionValueProperties.h index 6f7f4995ed15..405beefff6d1 100644 --- a/include/lldb/Interpreter/OptionValueProperties.h +++ b/include/lldb/Interpreter/OptionValueProperties.h @@ -61,7 +61,7 @@ class OptionValueProperties : DeepCopy () const; virtual Error - SetValueFromCString (const char *value, VarSetOperationType op = eVarSetOperationAssign); + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual void DumpValue (const ExecutionContext *exe_ctx, diff --git a/include/lldb/Interpreter/OptionValueRegex.h b/include/lldb/Interpreter/OptionValueRegex.h index 295bb98b69e6..5e04218dbfdf 100644 --- a/include/lldb/Interpreter/OptionValueRegex.h +++ b/include/lldb/Interpreter/OptionValueRegex.h @@ -49,7 +49,7 @@ class OptionValueRegex : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueSInt64.h b/include/lldb/Interpreter/OptionValueSInt64.h index 8bc8fb2da2d5..36ae97ccfcf8 100644 --- a/include/lldb/Interpreter/OptionValueSInt64.h +++ b/include/lldb/Interpreter/OptionValueSInt64.h @@ -77,7 +77,7 @@ class OptionValueSInt64 : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueString.h b/include/lldb/Interpreter/OptionValueString.h index a82e1403b74b..c75745d402be 100644 --- a/include/lldb/Interpreter/OptionValueString.h +++ b/include/lldb/Interpreter/OptionValueString.h @@ -137,7 +137,7 @@ class OptionValueString : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueUInt64.h b/include/lldb/Interpreter/OptionValueUInt64.h index 9b5496f9835c..51ff8818dcff 100644 --- a/include/lldb/Interpreter/OptionValueUInt64.h +++ b/include/lldb/Interpreter/OptionValueUInt64.h @@ -70,7 +70,7 @@ class OptionValueUInt64 : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValueUUID.h b/include/lldb/Interpreter/OptionValueUUID.h index caf436e576f5..c6ab48a627f6 100644 --- a/include/lldb/Interpreter/OptionValueUUID.h +++ b/include/lldb/Interpreter/OptionValueUUID.h @@ -53,7 +53,7 @@ class OptionValueUUID : public OptionValue DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); virtual Error - SetValueFromCString (const char *value, + SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); virtual bool diff --git a/include/lldb/Interpreter/OptionValues.h b/include/lldb/Interpreter/OptionValues.h index 2ccab994674b..44e1f0975826 100644 --- a/include/lldb/Interpreter/OptionValues.h +++ b/include/lldb/Interpreter/OptionValues.h @@ -21,6 +21,7 @@ #include "lldb/Interpreter/OptionValueFileSpec.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueFormat.h" +#include "lldb/Interpreter/OptionValueLanguage.h" #include "lldb/Interpreter/OptionValueFormatEntity.h" #include "lldb/Interpreter/OptionValuePathMappings.h" #include "lldb/Interpreter/OptionValueProperties.h" diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h index a1145b6f33d9..df281b533cba 100644 --- a/include/lldb/Interpreter/PythonDataObjects.h +++ b/include/lldb/Interpreter/PythonDataObjects.h @@ -17,12 +17,61 @@ // Project includes #include "lldb/lldb-defines.h" #include "lldb/Core/ConstString.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Core/Flags.h" #include "lldb/Interpreter/OptionValue.h" #include "lldb/lldb-python.h" namespace lldb_private { - +class PythonString; +class PythonList; +class PythonDictionary; +class PythonObject; +class PythonInteger; + +class StructuredPythonObject : public StructuredData::Generic +{ + public: + StructuredPythonObject() + : StructuredData::Generic() + { + } + + StructuredPythonObject(void *obj) + : StructuredData::Generic(obj) + { + Py_XINCREF(GetValue()); + } + + virtual ~StructuredPythonObject() + { + if (Py_IsInitialized()) + Py_XDECREF(GetValue()); + SetValue(nullptr); + } + + bool + IsValid() const override + { + return GetValue() && GetValue() != Py_None; + } + + void Dump(Stream &s) const override; + + private: + DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); +}; + +enum class PyObjectType +{ + Unknown, + None, + Integer, + Dictionary, + List, + String +}; + class PythonObject { public: @@ -42,8 +91,6 @@ namespace lldb_private { { Reset (rhs.m_py_obj); } - - explicit PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp); virtual ~PythonObject () @@ -89,6 +136,8 @@ namespace lldb_private { return m_py_obj; } + PyObjectType GetObjectType() const; + PythonString Repr (); @@ -102,7 +151,9 @@ namespace lldb_private { bool IsNULLOrNone () const; - + + StructuredData::ObjectSP CreateStructuredObject() const; + protected: PyObject* m_py_obj; }; @@ -110,25 +161,25 @@ namespace lldb_private { class PythonString: public PythonObject { public: - PythonString (); PythonString (PyObject *o); PythonString (const PythonObject &object); - PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp); - PythonString (const char* string); + PythonString (llvm::StringRef string); + PythonString (const char *string); virtual ~PythonString (); - + virtual bool Reset (PyObject* py_obj = NULL); - const char* + llvm::StringRef GetString() const; size_t GetSize() const; - void - SetString (const char* string); + void SetString(llvm::StringRef string); + + StructuredData::StringSP CreateStructuredString() const; }; class PythonInteger: public PythonObject @@ -138,18 +189,18 @@ namespace lldb_private { PythonInteger (); PythonInteger (PyObject* py_obj); PythonInteger (const PythonObject &object); - PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp); PythonInteger (int64_t value); virtual ~PythonInteger (); virtual bool Reset (PyObject* py_obj = NULL); - - int64_t - GetInteger(); - + + int64_t GetInteger() const; + void SetInteger (int64_t value); + + StructuredData::IntegerSP CreateStructuredInteger() const; }; class PythonList: public PythonObject @@ -159,24 +210,23 @@ namespace lldb_private { PythonList (bool create_empty); PythonList (PyObject* py_obj); PythonList (const PythonObject &object); - PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp); PythonList (uint32_t count); virtual ~PythonList (); virtual bool Reset (PyObject* py_obj = NULL); - - uint32_t - GetSize(); - - PythonObject - GetItemAtIndex (uint32_t index); - + + uint32_t GetSize() const; + + PythonObject GetItemAtIndex(uint32_t index) const; + void SetItemAtIndex (uint32_t index, const PythonObject &object); void AppendItem (const PythonObject &object); + + StructuredData::ArraySP CreateStructuredArray() const; }; class PythonDictionary: public PythonObject @@ -186,14 +236,13 @@ namespace lldb_private { explicit PythonDictionary (bool create_empty); PythonDictionary (PyObject* object); PythonDictionary (const PythonObject &object); - PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp); virtual ~PythonDictionary (); virtual bool Reset (PyObject* object = NULL); - - uint32_t GetSize(); - + + uint32_t GetSize() const; + PythonObject GetItemForKey (const PythonString &key) const; @@ -222,6 +271,8 @@ namespace lldb_private { void SetItemForKey (const PythonString &key, const PythonObject& value); + + StructuredData::DictionarySP CreateStructuredDictionary() const; }; } // namespace lldb_private diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h index 1b4b88161927..0f45dd8245e9 100644 --- a/include/lldb/Interpreter/ScriptInterpreter.h +++ b/include/lldb/Interpreter/ScriptInterpreter.h @@ -14,53 +14,12 @@ #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Error.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Utility/PseudoTerminal.h" namespace lldb_private { - -class ScriptInterpreterObject -{ -public: - ScriptInterpreterObject() : - m_object(NULL) - {} - - ScriptInterpreterObject(void* obj) : - m_object(obj) - {} - - ScriptInterpreterObject(const ScriptInterpreterObject& rhs) - : m_object(rhs.m_object) - {} - - virtual void* - GetObject() - { - return m_object; - } - - explicit operator bool () - { - return m_object != NULL; - } - - ScriptInterpreterObject& - operator = (const ScriptInterpreterObject& rhs) - { - if (this != &rhs) - m_object = rhs.m_object; - return *this; - } - - virtual - ~ScriptInterpreterObject() - {} - -protected: - void* m_object; -}; class ScriptInterpreterLocker { @@ -82,87 +41,6 @@ class ScriptInterpreter { public: - typedef void (*SWIGInitCallback) (void); - - typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::BreakpointLocationSP &bp_loc_sp); - - typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::WatchpointSP &wp_sp); - - typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, - void *session_dictionary, - const lldb::ValueObjectSP& valobj_sp, - void** pyfunct_wrapper, - const lldb::TypeSummaryOptionsSP& options, - std::string& retval); - - typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP& valobj_sp); - - typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ThreadPlanSP& thread_plan_sp); - - typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error); - - typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP& process_sp); - - typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor); - typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); - typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); - typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); - typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data); - typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data); - typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data); - typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor); - - typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger, - const char* args, - lldb_private::CommandReturnObject& cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - - typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger); - - typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name, - const char* session_dictionary_name, - lldb::ProcessSP& process, - std::string& output); - typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name, - const char* session_dictionary_name, - lldb::ThreadSP& thread, - std::string& output); - - typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name, - const char* session_dictionary_name, - lldb::TargetSP& target, - std::string& output); - - typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name, - const char* session_dictionary_name, - lldb::StackFrameSP& frame, - std::string& output); - - typedef bool (*SWIGPythonScriptKeyword_Value) (const char* python_function_name, - const char* session_dictionary_name, - lldb::ValueObjectSP& value, - std::string& output); - - typedef void* (*SWIGPython_GetDynamicSetting) (void* module, - const char* setting, - const lldb::TargetSP& target_sp); - typedef enum { eScriptReturnTypeCharPtr, @@ -324,95 +202,87 @@ class ScriptInterpreter { return false; } - - virtual lldb::ScriptInterpreterObjectSP - CreateSyntheticScriptedProvider (const char *class_name, - lldb::ValueObjectSP valobj) + + virtual StructuredData::ObjectSP + CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) { - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ObjectSP(); } - - virtual lldb::ScriptInterpreterObjectSP + + virtual StructuredData::GenericSP + CreateScriptCommandObject (const char *class_name) + { + return StructuredData::GenericSP(); + } + + virtual StructuredData::GenericSP OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp) { - return lldb::ScriptInterpreterObjectSP(); - } - - virtual lldb::ScriptInterpreterObjectSP - OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) - { - return lldb::ScriptInterpreterObjectSP(); - } - - virtual lldb::ScriptInterpreterObjectSP - OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) - { - return lldb::ScriptInterpreterObjectSP(); - } - - virtual lldb::ScriptInterpreterObjectSP - OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t thread_id) - { - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::GenericSP(); } - virtual lldb::ScriptInterpreterObjectSP - OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t tid, - lldb::addr_t context) + virtual StructuredData::DictionarySP + OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) { - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::DictionarySP(); } - - virtual lldb::ScriptInterpreterObjectSP - CreateScriptedThreadPlan (const char *class_name, - lldb::ThreadPlanSP thread_plan_sp) + + virtual StructuredData::ArraySP + OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) { - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ArraySP(); + } + + virtual StructuredData::StringSP + OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t thread_id) + { + return StructuredData::StringSP(); + } + + virtual StructuredData::DictionarySP + OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) + { + return StructuredData::DictionarySP(); + } + + virtual StructuredData::ObjectSP + CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp) + { + return StructuredData::ObjectSP(); } virtual bool - ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, - Event *event, - bool &script_error) + ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { script_error = true; return true; } virtual bool - ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, - Event *event, - bool &script_error) + ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { script_error = true; return true; } virtual lldb::StateType - ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, - bool &script_error) + ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) { script_error = true; return lldb::eStateStepping; } - virtual lldb::ScriptInterpreterObjectSP - LoadPluginModule (const FileSpec& file_spec, - lldb_private::Error& error) + virtual StructuredData::ObjectSP + LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) { - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::ObjectSP(); } - - virtual lldb::ScriptInterpreterObjectSP - GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp, - Target* target, - const char* setting_name, - lldb_private::Error& error) + + virtual StructuredData::DictionarySP + GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Error &error) { - return lldb::ScriptInterpreterObjectSP(); + return StructuredData::DictionarySP(); } virtual Error @@ -464,13 +334,10 @@ class ScriptInterpreter { return; } - + virtual bool - GetScriptedSummary (const char *function_name, - lldb::ValueObjectSP valobj, - lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, - const TypeSummaryOptions& options, - std::string& retval) + GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, + const TypeSummaryOptions &options, std::string &retval) { return false; } @@ -480,39 +347,39 @@ class ScriptInterpreter { // Clean up any ref counts to SBObjects that might be in global variables } - + virtual size_t - CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor) + CalculateNumChildren(const StructuredData::ObjectSP &implementor) { return 0; } - + virtual lldb::ValueObjectSP - GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor, uint32_t idx) + GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) { return lldb::ValueObjectSP(); } - + virtual int - GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name) + GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, const char *child_name) { return UINT32_MAX; } - + virtual bool - UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) + UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) { return false; } - + virtual bool - MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) + MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor) { return true; } - + virtual lldb::ValueObjectSP - GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor) + GetSyntheticValue(const StructuredData::ObjectSP &implementor) { return nullptr; } @@ -528,6 +395,17 @@ class ScriptInterpreter return false; } + virtual bool + RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, + const char* args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject& cmd_retobj, + Error& error, + const lldb_private::ExecutionContext& exe_ctx) + { + return false; + } + virtual bool RunScriptFormatKeyword (const char* impl_function, Process* process, @@ -585,6 +463,28 @@ class ScriptInterpreter return false; } + virtual bool + GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, + std::string& dest) + { + dest.clear(); + return false; + } + + virtual uint32_t + GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) + { + return 0; + } + + virtual bool + GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, + std::string& dest) + { + dest.clear(); + return false; + } + virtual bool CheckObjectExists (const char* name) { @@ -592,20 +492,17 @@ class ScriptInterpreter } virtual bool - LoadScriptingModule (const char* filename, - bool can_reload, - bool init_session, - lldb_private::Error& error, - lldb::ScriptInterpreterObjectSP* module_sp = nullptr) + LoadScriptingModule(const char *filename, bool can_reload, bool init_session, lldb_private::Error &error, + StructuredData::ObjectSP *module_sp = nullptr) { error.SetErrorString("loading unimplemented"); return false; } - - virtual lldb::ScriptInterpreterObjectSP - MakeScriptObject (void* object) + + virtual bool + IsReservedWord (const char* word) { - return lldb::ScriptInterpreterObjectSP(new ScriptInterpreterObject(object)); + return false; } virtual std::unique_ptr @@ -622,32 +519,6 @@ class ScriptInterpreter static std::string LanguageToString (lldb::ScriptLanguage language); - - static void - InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction swig_breakpoint_callback, - SWIGWatchpointCallbackFunction swig_watchpoint_callback, - SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, - SWIGPythonCreateSyntheticProvider swig_synthetic_script, - SWIGPythonCalculateNumChildren swig_calc_children, - SWIGPythonGetChildAtIndex swig_get_child_index, - SWIGPythonGetIndexOfChildWithName swig_get_index_child, - SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , - SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, - SWIGPythonUpdateSynthProviderInstance swig_update_provider, - SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, - SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, - SWIGPythonCallCommand swig_call_command, - SWIGPythonCallModuleInit swig_call_module_init, - SWIGPythonCreateOSPlugin swig_create_os_plugin, - SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, - SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, - SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, - SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, - SWIGPython_GetDynamicSetting swig_plugin_get, - SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, - SWIGPythonCallThreadPlan swig_call_thread_plan); virtual void ResetOutputFileHandle (FILE *new_fh) { } //By default, do nothing. diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h index 94ed16e02ca2..058058ecccb5 100644 --- a/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -33,8 +33,99 @@ class ScriptInterpreterPython : public IOHandlerDelegateMultiline { public: + typedef void (*SWIGInitCallback) (void); - friend class IOHandlerPythonInterpreter; + typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& frame_sp, + const lldb::BreakpointLocationSP &bp_loc_sp); + + typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& frame_sp, + const lldb::WatchpointSP &wp_sp); + + typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, + void *session_dictionary, + const lldb::ValueObjectSP& valobj_sp, + void** pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP& options, + std::string& retval); + + typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp); + + typedef void* (*SWIGPythonCreateCommandObject) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::DebuggerSP debugger_sp); + + typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ThreadPlanSP& thread_plan_sp); + + typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error); + + typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP& process_sp); + + typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor); + typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); + typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); + typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); + typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data); + typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data); + typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data); + typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor); + + typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject& cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); + + typedef bool (*SWIGPythonCallCommandObject) (void *implementor, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject& cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); + + + typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger); + + typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name, + const char* session_dictionary_name, + lldb::ProcessSP& process, + std::string& output); + typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name, + const char* session_dictionary_name, + lldb::ThreadSP& thread, + std::string& output); + + typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name, + const char* session_dictionary_name, + lldb::TargetSP& target, + std::string& output); + + typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name, + const char* session_dictionary_name, + lldb::StackFrameSP& frame, + std::string& output); + + typedef bool (*SWIGPythonScriptKeyword_Value) (const char* python_function_name, + const char* session_dictionary_name, + lldb::ValueObjectSP& value, + std::string& output); + + typedef void* (*SWIGPython_GetDynamicSetting) (void* module, + const char* setting, + const lldb::TargetSP& target_sp); + + friend class ::IOHandlerPythonInterpreter; ScriptInterpreterPython (CommandInterpreter &interpreter); @@ -79,74 +170,45 @@ class ScriptInterpreterPython : bool GenerateScriptAliasFunction (StringList &input, std::string& output) override; - - lldb::ScriptInterpreterObjectSP - CreateSyntheticScriptedProvider (const char *class_name, - lldb::ValueObjectSP valobj) override; - lldb::ScriptInterpreterObjectSP - CreateScriptedThreadPlan (const char *class_name, - lldb::ThreadPlanSP thread_plan) override; + StructuredData::ObjectSP CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) override; + + StructuredData::GenericSP CreateScriptCommandObject (const char *class_name) override; + + StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan) override; + + bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; + bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; + lldb::StateType ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override; + + StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override; + + StructuredData::DictionarySP OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + + StructuredData::ArraySP OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + + StructuredData::StringSP OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t thread_id) override; + + StructuredData::DictionarySP OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, + lldb::addr_t context) override; + + StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) override; + + StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, + lldb_private::Error &error) override; + + size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor) override; + + lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override; + + int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, const char *child_name) override; + + bool UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) override; + + bool MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor) override; + + lldb::ValueObjectSP GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; - bool - ScriptedThreadPlanExplainsStop (lldb::ScriptInterpreterObjectSP implementor_sp, - Event *event, - bool &script_error) override; - bool - ScriptedThreadPlanShouldStop (lldb::ScriptInterpreterObjectSP implementor_sp, - Event *event, - bool &script_error) override; - lldb::StateType - ScriptedThreadPlanGetRunState (lldb::ScriptInterpreterObjectSP implementor_sp, - bool &script_error) override; - - lldb::ScriptInterpreterObjectSP - OSPlugin_CreatePluginObject (const char *class_name, - lldb::ProcessSP process_sp) override; - - lldb::ScriptInterpreterObjectSP - OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) override; - - lldb::ScriptInterpreterObjectSP - OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) override; - - lldb::ScriptInterpreterObjectSP - OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t thread_id) override; - - lldb::ScriptInterpreterObjectSP - OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, - lldb::tid_t tid, - lldb::addr_t context) override; - - lldb::ScriptInterpreterObjectSP - LoadPluginModule (const FileSpec& file_spec, - lldb_private::Error& error) override; - - lldb::ScriptInterpreterObjectSP - GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp, - Target* target, - const char* setting_name, - lldb_private::Error& error) override; - - size_t - CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor) override; - - lldb::ValueObjectSP - GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor, uint32_t idx) override; - - int - GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name) override; - - bool - UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) override; - - bool - MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) override; - - lldb::ValueObjectSP - GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor) override; - bool RunScriptBasedCommand(const char* impl_function, const char* args, @@ -155,6 +217,14 @@ class ScriptInterpreterPython : Error& error, const lldb_private::ExecutionContext& exe_ctx) override; + bool + RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, + const char* args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject& cmd_retobj, + Error& error, + const lldb_private::ExecutionContext& exe_ctx) override; + Error GenerateFunction(const char *signature, const StringList &input) override; @@ -188,20 +258,25 @@ class ScriptInterpreterPython : WatchpointCallbackFunction (void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id); - - bool - GetScriptedSummary (const char *function_name, - lldb::ValueObjectSP valobj, - lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, - const TypeSummaryOptions& options, - std::string& retval) override; - + + bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, + const TypeSummaryOptions &options, std::string &retval) override; + void Clear () override; bool GetDocumentationForItem (const char* item, std::string& dest) override; + bool + GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override; + + uint32_t + GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) override; + + bool + GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override; + bool CheckObjectExists (const char* name) override { @@ -240,17 +315,13 @@ class ScriptInterpreterPython : ValueObject* value, std::string& output, Error& error) override; - + + bool LoadScriptingModule(const char *filename, bool can_reload, bool init_session, lldb_private::Error &error, + StructuredData::ObjectSP *module_sp = nullptr) override; + bool - LoadScriptingModule (const char* filename, - bool can_reload, - bool init_session, - lldb_private::Error& error, - lldb::ScriptInterpreterObjectSP* module_sp = nullptr) override; - - lldb::ScriptInterpreterObjectSP - MakeScriptObject (void* object) override; - + IsReservedWord (const char* word) override; + std::unique_ptr AcquireInterpreterLock () override; @@ -278,10 +349,9 @@ class ScriptInterpreterPython : StringList ReadCommandInputFromUser (FILE *in_file); - - virtual void - ResetOutputFileHandle (FILE *new_fh) override; - + + void ResetOutputFileHandle(FILE *new_fh) override; + static void InitializePrivate (); @@ -291,6 +361,7 @@ class ScriptInterpreterPython : SWIGWatchpointCallbackFunction swig_watchpoint_callback, SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, SWIGPythonCreateSyntheticProvider swig_synthetic_script, + SWIGPythonCreateCommandObject swig_create_cmd, SWIGPythonCalculateNumChildren swig_calc_children, SWIGPythonGetChildAtIndex swig_get_child_index, SWIGPythonGetIndexOfChildWithName swig_get_index_child, @@ -300,6 +371,7 @@ class ScriptInterpreterPython : SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, + SWIGPythonCallCommandObject swig_call_command_object, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, @@ -369,35 +441,6 @@ class ScriptInterpreterPython : ~SynchronicityHandler(); }; - class ScriptInterpreterPythonObject : public ScriptInterpreterObject - { - public: - ScriptInterpreterPythonObject() : - ScriptInterpreterObject() - {} - - ScriptInterpreterPythonObject(void* obj) : - ScriptInterpreterObject(obj) - { - Py_XINCREF(m_object); - } - - explicit operator bool () - { - return m_object && m_object != Py_None; - } - - - virtual - ~ScriptInterpreterPythonObject() - { - if (Py_IsInitialized()) - Py_XDECREF(m_object); - m_object = NULL; - } - private: - DISALLOW_COPY_AND_ASSIGN (ScriptInterpreterPythonObject); - }; public: class Locker : public ScriptInterpreterLocker { @@ -450,6 +493,13 @@ class ScriptInterpreterPython : PyGILState_STATE m_GILState; }; protected: + enum class AddLocation + { + Beginning, + End + }; + + static void AddToSysPath(AddLocation location, std::string path); uint32_t IsExecutingPython () const diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h index a9096fe66151..a411e42fe0c5 100644 --- a/include/lldb/Symbol/ClangASTContext.h +++ b/include/lldb/Symbol/ClangASTContext.h @@ -235,7 +235,7 @@ class ClangASTContext clang::IdentifierInfo &myIdent = ast->Idents.get(type_name.GetCString()); clang::DeclarationName myName = ast->DeclarationNames.getIdentifier(&myIdent); - clang::DeclContext::lookup_const_result result = ast->getTranslationUnitDecl()->lookup(myName); + clang::DeclContext::lookup_result result = ast->getTranslationUnitDecl()->lookup(myName); if (!result.empty()) { diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h index 94c768780a00..2524751e092e 100644 --- a/include/lldb/Symbol/ClangASTType.h +++ b/include/lldb/Symbol/ClangASTType.h @@ -351,10 +351,10 @@ class ClangASTType //---------------------------------------------------------------------- uint64_t - GetByteSize (ExecutionContext *exe_ctx) const; + GetByteSize (ExecutionContextScope *exe_scope) const; uint64_t - GetBitSize (ExecutionContext *exe_ctx) const; + GetBitSize (ExecutionContextScope *exe_scope) const; lldb::Encoding GetEncoding (uint64_t &count) const; diff --git a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h index 0c8121135ef0..41bb235636f0 100644 --- a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h +++ b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h @@ -34,13 +34,11 @@ class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); typedef void (*FindExternalVisibleDeclsByNameCallback)(void *baton, const clang::DeclContext *DC, clang::DeclarationName Name, llvm::SmallVectorImpl *results); - typedef bool (*LayoutRecordTypeCallback)(void *baton, - const clang::RecordDecl *Record, - uint64_t &Size, - uint64_t &Alignment, - llvm::DenseMap &FieldOffsets, - llvm::DenseMap &BaseOffsets, - llvm::DenseMap &VirtualBaseOffsets); + typedef bool (*LayoutRecordTypeCallback)( + void *baton, const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets); ClangExternalASTSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, CompleteObjCInterfaceDeclCallback objc_decl_callback, @@ -59,39 +57,39 @@ class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon // clang::ExternalASTSource //------------------------------------------------------------------ - virtual clang::Decl * - GetExternalDecl (uint32_t ID) + clang::Decl * + GetExternalDecl(uint32_t ID) override { // This method only needs to be implemented if the AST source ever // passes back decl sets as VisibleDeclaration objects. return 0; } - - virtual clang::Stmt * - GetExternalDeclStmt (uint64_t Offset) + + clang::Stmt * + GetExternalDeclStmt(uint64_t Offset) override { // This operation is meant to be used via a LazyOffsetPtr. It only // needs to be implemented if the AST source uses methods like // FunctionDecl::setLazyBody when building decls. return 0; } - - virtual clang::Selector - GetExternalSelector (uint32_t ID) + + clang::Selector + GetExternalSelector(uint32_t ID) override { // This operation only needs to be implemented if the AST source // returns non-zero for GetNumKnownSelectors(). return clang::Selector(); } - virtual uint32_t - GetNumExternalSelectors() + uint32_t + GetNumExternalSelectors() override { return 0; } - - virtual clang::CXXBaseSpecifier * - GetExternalCXXBaseSpecifiers(uint64_t Offset) + + clang::CXXBaseSpecifier * + GetExternalCXXBaseSpecifiers(uint64_t Offset) override { return NULL; } @@ -101,34 +99,26 @@ class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon { return; } - - virtual clang::ExternalLoadResult - FindExternalLexicalDecls (const clang::DeclContext *decl_ctx, - bool (*isKindWeWant)(clang::Decl::Kind), - llvm::SmallVectorImpl &decls) + + clang::ExternalLoadResult + FindExternalLexicalDecls(const clang::DeclContext *decl_ctx, bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl &decls) override { // This is used to support iterating through an entire lexical context, // which isn't something the debugger should ever need to do. return clang::ELR_Failure; } - - virtual bool - FindExternalVisibleDeclsByName (const clang::DeclContext *decl_ctx, - clang::DeclarationName decl_name); - - virtual void - CompleteType (clang::TagDecl *tag_decl); - - virtual void - CompleteType (clang::ObjCInterfaceDecl *objc_decl); - - bool - layoutRecordType(const clang::RecordDecl *Record, - uint64_t &Size, - uint64_t &Alignment, - llvm::DenseMap &FieldOffsets, - llvm::DenseMap &BaseOffsets, - llvm::DenseMap &VirtualBaseOffsets); + + bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName decl_name) override; + + void CompleteType(clang::TagDecl *tag_decl) override; + + void CompleteType(clang::ObjCInterfaceDecl *objc_decl) override; + + bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override; void SetExternalSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, CompleteObjCInterfaceDeclCallback objc_decl_callback, diff --git a/include/lldb/Symbol/CompileUnit.h b/include/lldb/Symbol/CompileUnit.h index f9238ebba18c..e0c069352bf4 100644 --- a/include/lldb/Symbol/CompileUnit.h +++ b/include/lldb/Symbol/CompileUnit.h @@ -256,6 +256,18 @@ class CompileUnit : //------------------------------------------------------------------ FileSpecList& GetSupportFiles (); + + //------------------------------------------------------------------ + /// Get the compile unit's imported module list. + /// + /// This reports all the imports that the compile unit made, + /// including the current module. + /// + /// @return + /// A list of imported module names. + //------------------------------------------------------------------ + const std::vector & + GetImportedModules (); //------------------------------------------------------------------ /// Get the SymbolFile plug-in user data. @@ -400,6 +412,8 @@ class CompileUnit : Flags m_flags; ///< Compile unit flags that help with partial parsing. std::vector m_functions; ///< The sparsely populated list of shared pointers to functions ///< that gets populated as functions get partially parsed. + std::vector m_imported_modules; ///< All modules, including the current module, imported by this + ///< compile unit. FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations. std::unique_ptr m_line_table_ap; ///< Line table that will get parsed on demand. lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand. @@ -407,11 +421,12 @@ class CompileUnit : private: enum { - flagsParsedAllFunctions = (1u << 0), ///< Have we already parsed all our functions - flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics? - flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit? - flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already? - flagsParsedLanguage = (1u << 4) ///< Have we parsed the line table already? + flagsParsedAllFunctions = (1u << 0), ///< Have we already parsed all our functions + flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics? + flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit? + flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already? + flagsParsedLanguage = (1u << 4), ///< Have we parsed the line table already? + flagsParsedImportedModules = (1u << 5) ///< Have we parsed the imported modules already? }; DISALLOW_COPY_AND_ASSIGN (CompileUnit); diff --git a/include/lldb/Symbol/DWARFCallFrameInfo.h b/include/lldb/Symbol/DWARFCallFrameInfo.h index 27d1a52b49f8..cc497c039a4e 100644 --- a/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -131,6 +131,16 @@ class DWARFCallFrameInfo void GetCFIData(); + // Applies the specified DWARF opcode to the given row. This function handle the commands + // operates only on a single row (these are the ones what can appear both in CIE and in FDE). + // Returns true if the opcode is handled and false otherwise. + bool + HandleCommonDwarfOpcode(uint8_t primary_opcode, + uint8_t extended_opcode, + int32_t data_align, + lldb::offset_t& offset, + UnwindPlan::Row& row); + ObjectFile& m_objfile; lldb::SectionSP m_section_sp; lldb::RegisterKind m_reg_kind; diff --git a/include/lldb/Symbol/FuncUnwinders.h b/include/lldb/Symbol/FuncUnwinders.h index 1e579c42acb8..0d4aabb5fd57 100644 --- a/include/lldb/Symbol/FuncUnwinders.h +++ b/include/lldb/Symbol/FuncUnwinders.h @@ -50,7 +50,7 @@ class FuncUnwinders GetUnwindPlanAtNonCallSite (Target& target, lldb_private::Thread& thread, int current_offset); lldb::UnwindPlanSP - GetUnwindPlanFastUnwind (lldb_private::Thread& Thread); + GetUnwindPlanFastUnwind (Target& target, lldb_private::Thread& thread); lldb::UnwindPlanSP GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread); @@ -111,7 +111,7 @@ class FuncUnwinders private: lldb::UnwindAssemblySP - GetUnwindAssemblyProfiler (); + GetUnwindAssemblyProfiler (Target& target); UnwindTable& m_unwind_table; AddressRange m_range; diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h index 8bcf92de42e5..ff00ac26e67e 100644 --- a/include/lldb/Symbol/ObjectFile.h +++ b/include/lldb/Symbol/ObjectFile.h @@ -836,6 +836,13 @@ friend class lldb_private::Module; { return m_memory_addr != LLDB_INVALID_ADDRESS; } + + // Strip linker annotations (such as @@VERSION) from symbol names. + virtual std::string + StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const + { + return symbol_name.str(); + } protected: //------------------------------------------------------------------ diff --git a/include/lldb/Symbol/Symbol.h b/include/lldb/Symbol/Symbol.h index 0dd04b7112bc..ad11563634ea 100644 --- a/include/lldb/Symbol/Symbol.h +++ b/include/lldb/Symbol/Symbol.h @@ -39,11 +39,11 @@ class Symbol : lldb::addr_t value, lldb::addr_t size, bool size_is_valid, + bool contains_linker_annotations, uint32_t flags); Symbol (uint32_t symID, - const char *name, - bool name_is_mangled, + const Mangled &mangled, lldb::SymbolType type, bool external, bool is_debug, @@ -51,6 +51,7 @@ class Symbol : bool is_artificial, const AddressRange &range, bool size_is_valid, + bool contains_linker_annotations, uint32_t flags); Symbol (const Symbol& rhs); @@ -71,25 +72,81 @@ class Symbol : ValueIsAddress() const; //------------------------------------------------------------------ - // Access the address value. Do NOT hand out the AddressRange as an - // object as the byte size of the address range may not be filled in - // and it should be accessed via GetByteSize(). + // The GetAddressRef() accessor functions should only be called if + // you previously call ValueIsAddress() otherwise you might get an + // reference to an Address object that contains an constant integer + // value in m_addr_range.m_base_addr.m_offset which could be + // incorrectly used to represent an absolute address since it has + // no section. //------------------------------------------------------------------ Address & - GetAddress() + GetAddressRef() { return m_addr_range.GetBaseAddress(); } + const Address & + GetAddressRef() const + { + return m_addr_range.GetBaseAddress(); + } + + //------------------------------------------------------------------ + // Makes sure the symbol's value is an address and returns the file + // address. Returns LLDB_INVALID_ADDRESS if the symbol's value isn't + // an address. + //------------------------------------------------------------------ + lldb::addr_t + GetFileAddress () const; + + //------------------------------------------------------------------ + // Makes sure the symbol's value is an address and gets the load + // address using \a target if it is. Returns LLDB_INVALID_ADDRESS + // if the symbol's value isn't an address or if the section isn't + // loaded in \a target. + //------------------------------------------------------------------ + lldb::addr_t + GetLoadAddress (Target *target) const; + //------------------------------------------------------------------ // Access the address value. Do NOT hand out the AddressRange as an // object as the byte size of the address range may not be filled in // and it should be accessed via GetByteSize(). //------------------------------------------------------------------ - const Address & + Address GetAddress() const { - return m_addr_range.GetBaseAddress(); + // Make sure the our value is an address before we hand a copy out. + // We use the Address inside m_addr_range to contain the value for + // symbols that are not address based symbols so we are using it + // for more than just addresses. For example undefined symbols on + // MacOSX have a nlist.n_value of 0 (zero) and this will get placed + // into m_addr_range.m_base_addr.m_offset and it will have no section. + // So in the GetAddress() accessor, we need to hand out an invalid + // address if the symbol's value isn't an address. + if (ValueIsAddress()) + return m_addr_range.GetBaseAddress(); + else + return Address(); + } + + // 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 "fail_value" if the symbol is an address value. + uint64_t + GetIntegerValue (uint64_t fail_value = 0) const + { + if (ValueIsAddress()) + { + // This symbol's value is an address. Use Symbol::GetAddress() to get the address. + return fail_value; + } + else + { + // The value is stored in the base address' offset + return m_addr_range.GetBaseAddress().GetOffset(); + } } lldb::addr_t @@ -131,7 +188,7 @@ class Symbol : FileSpec GetReExportedSymbolSharedLibrary () const; - bool + void SetReExportedSymbolName(const ConstString &name); bool @@ -272,6 +329,16 @@ class Symbol : m_demangled_is_synthesized = b; } + bool + ContainsLinkerAnnotations() const + { + return m_contains_linker_annotations; + } + void + SetContainsLinkerAnnotations(bool b) + { + m_contains_linker_annotations = b; + } //------------------------------------------------------------------ /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) /// @@ -325,7 +392,8 @@ class Symbol : m_size_is_synthesized:1,// non-zero if this symbol's size was calculated using a delta between this symbol and the next m_size_is_valid:1, m_demangled_is_synthesized:1, // The demangled name was created should not be used for expressions or other lookups - m_type:8; + m_contains_linker_annotations:1, // The symbol name contains linker annotations, which are optional when doing name lookups + m_type:7; Mangled m_mangled; // uniqued symbol name/mangled name pair AddressRange m_addr_range; // Contains the value, or the section offset address when the value is an address in a section, and the size (if any) uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h index 64490627b84d..c48505e1064a 100644 --- a/include/lldb/Symbol/SymbolContext.h +++ b/include/lldb/Symbol/SymbolContext.h @@ -161,6 +161,32 @@ class SymbolContext /// /// @param[in] so_addr /// The resolved section offset address. + /// + /// @param[in] show_fullpaths + /// When printing file paths (with the Module), whether the + /// base name of the Module should be printed or the full path. + /// + /// @param[in] show_module + /// Whether the module name should be printed followed by a + /// grave accent "`" character. + /// + /// @param[in] show_inlined_frames + /// If a given pc is in inlined function(s), whether the inlined + /// functions should be printed on separate lines in addition to + /// the concrete function containing the pc. + /// + /// @param[in] show_function_arguments + /// If false, this method will try to elide the function argument + /// types when printing the function name. This may be ambiguous + /// for languages that have function overloading - but it may + /// make the "function name" too long to include all the argument + /// types. + /// + /// @param[in] show_function_name + /// Normally this should be true - the function/symbol name should + /// be printed. In disassembly formatting, where we want a format + /// like "<*+36>", this should be false and "*" will be printed + /// instead. //------------------------------------------------------------------ bool DumpStopContext (Stream *s, @@ -169,7 +195,8 @@ class SymbolContext bool show_fullpaths, bool show_module, bool show_inlined_frames, - bool show_function_arguments) const; + bool show_function_arguments, + bool show_function_name) const; //------------------------------------------------------------------ /// Get the address range contained within a symbol context. diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h index 6df3d49fc464..0efe034235d5 100644 --- a/include/lldb/Symbol/SymbolFile.h +++ b/include/lldb/Symbol/SymbolFile.h @@ -124,6 +124,7 @@ class SymbolFile : virtual size_t ParseCompileUnitFunctions (const SymbolContext& sc) = 0; virtual bool ParseCompileUnitLineTable (const SymbolContext& sc) = 0; virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) = 0; + virtual bool ParseImportedModules (const SymbolContext &sc, std::vector &imported_modules) = 0; virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0; virtual size_t ParseTypes (const SymbolContext& sc) = 0; virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0; diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h index 82f902d4e07b..248918af2833 100644 --- a/include/lldb/Symbol/SymbolVendor.h +++ b/include/lldb/Symbol/SymbolVendor.h @@ -66,6 +66,10 @@ class SymbolVendor : virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files); + + virtual bool + ParseImportedModules (const SymbolContext &sc, + std::vector &imported_modules); virtual size_t ParseFunctionBlocks (const SymbolContext& sc); @@ -164,6 +168,9 @@ class SymbolVendor : return m_sym_file_ap.get(); } + FileSpec + GetMainFileSpec() const; + // Get module unified section list symbol table. virtual Symtab * GetSymtab (); diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h index dc08333e22fb..cf28c7e87ac5 100644 --- a/include/lldb/Symbol/Symtab.h +++ b/include/lldb/Symbol/Symtab.h @@ -58,6 +58,14 @@ class Symtab Symbol * SymbolAtIndex (size_t idx); const Symbol * SymbolAtIndex (size_t idx) const; Symbol * FindSymbolWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t &start_idx); + //---------------------------------------------------------------------- + /// Get the parent symbol for the given symbol. + /// + /// Many symbols in symbol tables are scoped by other symbols that + /// contain one or more symbol. This function will look for such a + /// containing symbol and return it if there is one. + //---------------------------------------------------------------------- + const Symbol * GetParent (Symbol *symbol) const; uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, std::vector& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; uint32_t AppendSymbolIndexesWithTypeAndFlagsValue (lldb::SymbolType symbol_type, uint32_t flags_value, std::vector& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector& matches, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h index 51bd3dd82c92..c1784cb364a8 100644 --- a/include/lldb/Symbol/Type.h +++ b/include/lldb/Symbol/Type.h @@ -71,7 +71,12 @@ class Type : eEncodingIsSyntheticUID } EncodingDataType; - typedef enum ResolveStateTag + // We must force the underlying type of the enum to be unsigned here. Not all compilers + // behave the same with regards to the default underlying type of an enum, but because + // this enum is used in an enum bitfield and integer comparisons are done with the value + // we need to guarantee that it's always unsigned so that, for example, eResolveStateFull + // doesn't compare less than eResolveStateUnresolved when used in a 2-bit bitfield. + typedef enum ResolveStateTag : unsigned { eResolveStateUnresolved = 0, eResolveStateForward = 1, @@ -300,7 +305,12 @@ class Type : ClangASTType m_clang_type; struct Flags { +#ifdef __GNUC__ + // using unsigned type here to work around a very noisy gcc warning + unsigned clang_type_resolve_state : 2; +#else ResolveState clang_type_resolve_state : 2; +#endif bool is_complete_objc_class : 1; } m_flags; diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h index c482739cb8f6..bfc008a5b6bc 100644 --- a/include/lldb/Symbol/UnwindPlan.h +++ b/include/lldb/Symbol/UnwindPlan.h @@ -237,17 +237,178 @@ class UnwindPlan { } m_location; }; + class CFAValue + { + public: + + enum ValueType + { + unspecified, // not specified + isRegisterPlusOffset, // CFA = register + offset + isRegisterDereferenced, // CFA = [reg] + isDWARFExpression // CFA = eval(dwarf_expr) + }; + + CFAValue() : + m_type(unspecified), + m_value() + { + } + + bool + operator == (const CFAValue& rhs) const; + + bool + operator != (const CFAValue &rhs) const + { + return !(*this == rhs); + } + + void + SetUnspecified() + { + m_type = unspecified; + } + + bool + IsUnspecified () const + { + return m_type == unspecified; + } + + bool + IsRegisterPlusOffset () const + { + return m_type == isRegisterPlusOffset; + } + + void + SetIsRegisterPlusOffset (uint32_t reg_num, int32_t offset) + { + m_type = isRegisterPlusOffset; + m_value.reg.reg_num = reg_num; + m_value.reg.offset = offset; + } + + bool + IsRegisterDereferenced () const + { + return m_type == isRegisterDereferenced; + } + + void + SetIsRegisterDereferenced (uint32_t reg_num) + { + m_type = isRegisterDereferenced; + m_value.reg.reg_num = reg_num; + } + + bool + IsDWARFExpression () const + { + return m_type == isDWARFExpression; + } + + void + SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len) + { + m_type = isDWARFExpression; + m_value.expr.opcodes = opcodes; + m_value.expr.length = len; + } + + uint32_t + GetRegisterNumber () const + { + if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset) + return m_value.reg.reg_num; + return LLDB_INVALID_REGNUM; + } + + ValueType + GetValueType () const + { + return m_type; + } + + int32_t + GetOffset () const + { + if (m_type == isRegisterPlusOffset) + return m_value.reg.offset; + return 0; + } + + void IncOffset (int32_t delta) + { + if (m_type == isRegisterPlusOffset) + m_value.reg.offset += delta; + } + + void SetOffset (int32_t offset) + { + if (m_type == isRegisterPlusOffset) + m_value.reg.offset = offset; + } + + void + GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const + { + if (m_type == isDWARFExpression) + { + *opcodes = m_value.expr.opcodes; + len = m_value.expr.length; + } + else + { + *opcodes = NULL; + len = 0; + } + } + + const uint8_t * + GetDWARFExpressionBytes () + { + if (m_type == isDWARFExpression) + return m_value.expr.opcodes; + return NULL; + } + + int + GetDWARFExpressionLength () + { + if (m_type == isDWARFExpression) + return m_value.expr.length; + return 0; + } + + void + Dump (Stream &s, + const UnwindPlan* unwind_plan, + Thread* thread) const; + + private: + ValueType m_type; // How do we compute CFA value? + union + { + struct { + // For m_type == isRegisterPlusOffset or m_type == isRegisterDereferenced + uint32_t reg_num; // The register number + // For m_type == isRegisterPlusOffset + int32_t offset; + } reg; + // For m_type == isDWARFExpression + struct { + const uint8_t *opcodes; + uint16_t length; + } expr; + } m_value; + }; // class CFAValue + public: Row (); - - Row (const UnwindPlan::Row& rhs) : - m_offset (rhs.m_offset), - m_cfa_type (rhs.m_cfa_type), - m_cfa_reg_num (rhs.m_cfa_reg_num), - m_cfa_offset (rhs.m_cfa_offset), - m_register_locations (rhs.m_register_locations) - { - } + + Row (const UnwindPlan::Row& rhs) = default; bool operator == (const Row &rhs) const; @@ -279,47 +440,9 @@ class UnwindPlan { m_offset += offset; } - // How we can reconstruct the CFA address for this stack frame, at this location - enum CFAType + CFAValue& GetCFAValue() { - CFAIsRegisterPlusOffset, // the CFA value in a register plus (or minus) an offset - CFAIsRegisterDereferenced // the address in a register is dereferenced to get CFA value - }; - - CFAType - GetCFAType () const - { - return m_cfa_type; - } - - void - SetCFAType (CFAType cfa_type) - { - m_cfa_type = cfa_type; - } - - // If GetCFAType() is CFAIsRegisterPlusOffset, add GetCFAOffset to the reg value to get CFA value - // If GetCFAType() is CFAIsRegisterDereferenced, dereference the addr in the reg to get CFA value - uint32_t - GetCFARegister () const - { - return m_cfa_reg_num; - } - - void - SetCFARegister (uint32_t reg_num); - - // This should not be used when GetCFAType() is CFAIsRegisterDereferenced; will return 0 in that case. - int32_t - GetCFAOffset () const - { - return m_cfa_offset; - } - - void - SetCFAOffset (int32_t offset) - { - m_cfa_offset = offset; + return m_cfa_value; } bool @@ -360,14 +483,7 @@ class UnwindPlan { typedef std::map collection; lldb::addr_t m_offset; // Offset into the function for this row - CFAType m_cfa_type; - - // If m_cfa_type == CFAIsRegisterPlusOffset, the CFA address is computed as m_cfa_reg_num + m_cfa_offset - // If m_cfa_type == CFAIsRegisterDereferenced, the CFA address is computed as *(m_cfa_reg_num) - i.e. the - // address in m_cfa_reg_num is dereferenced and the pointer value read is the CFA addr. - uint32_t m_cfa_reg_num; // The Call Frame Address register number - int32_t m_cfa_offset; // The offset from the CFA for this row - + CFAValue m_cfa_value; collection m_register_locations; }; // class Row @@ -388,6 +504,22 @@ class UnwindPlan { { } + // Performs a deep copy of the plan, including all the rows (expensive). + UnwindPlan (const UnwindPlan &rhs) : + m_plan_valid_address_range (rhs.m_plan_valid_address_range), + m_register_kind (rhs.m_register_kind), + m_return_addr_register (rhs.m_return_addr_register), + m_source_name (rhs.m_source_name), + m_plan_is_sourced_from_compiler (rhs.m_plan_is_sourced_from_compiler), + m_plan_is_valid_at_all_instruction_locations (rhs.m_plan_is_valid_at_all_instruction_locations), + m_lsda_address (rhs.m_lsda_address), + m_personality_func_addr (rhs.m_personality_func_addr) + { + m_row_list.reserve (rhs.m_row_list.size()); + for (const RowSP &row_sp: rhs.m_row_list) + m_row_list.emplace_back (new Row (*row_sp)); + } + ~UnwindPlan () { } @@ -437,7 +569,7 @@ class UnwindPlan { { if (m_row_list.empty()) return LLDB_INVALID_REGNUM; - return m_row_list.front()->GetCFARegister(); + return m_row_list.front()->GetCFAValue().GetRegisterNumber(); } // This UnwindPlan may not be valid at every address of the function span. diff --git a/include/lldb/Symbol/Variable.h b/include/lldb/Symbol/Variable.h index 07295d090ee6..a345bcb8c23a 100644 --- a/include/lldb/Symbol/Variable.h +++ b/include/lldb/Symbol/Variable.h @@ -29,7 +29,7 @@ class Variable : public UserID //------------------------------------------------------------------ Variable (lldb::user_id_t uid, const char *name, - const char *mangled, // The mangled variable name for variables in namespaces + const char *mangled, // The mangled or fully qualified name of the variable. const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope, SymbolContextScope *owner_scope, diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h index 43df9e67add0..3e51453566b3 100644 --- a/include/lldb/Target/CPPLanguageRuntime.h +++ b/include/lldb/Target/CPPLanguageRuntime.h @@ -153,6 +153,9 @@ class CPPLanguageRuntime : static uint32_t FindEquivalentNames(ConstString type_name, std::vector& equivalents); + virtual size_t + GetAlternateManglings(const ConstString &mangled, std::vector &alternates) = 0; + protected: //------------------------------------------------------------------ // Classes that inherit from CPPLanguageRuntime can see and modify these diff --git a/include/lldb/Target/FileAction.h b/include/lldb/Target/FileAction.h index 4015cbb5ea89..907c4d937beb 100644 --- a/include/lldb/Target/FileAction.h +++ b/include/lldb/Target/FileAction.h @@ -11,6 +11,7 @@ #define liblldb_Target_FileAction_h #include +#include "lldb/Host/FileSpec.h" namespace lldb_private { @@ -34,7 +35,7 @@ class FileAction bool Duplicate(int fd, int dup_fd); - bool Open(int fd, const char *path, bool read, bool write); + bool Open(int fd, const FileSpec &file_spec, bool read, bool write); int GetFD() const @@ -54,16 +55,20 @@ class FileAction return m_arg; } - const char *GetPath() const; + const char * + GetPath() const; + + const FileSpec & + GetFileSpec() const; void Dump (Stream &stream) const; protected: - Action m_action; // The action for this file - int m_fd; // An existing file descriptor - int m_arg; // oflag for eFileActionOpen*, dup_fd for eFileActionDuplicate - std::string m_path; // A file path to use for opening after fork or posix_spawn + Action m_action; // The action for this file + int m_fd; // An existing file descriptor + int m_arg; // oflag for eFileActionOpen*, dup_fd for eFileActionDuplicate + FileSpec m_file_spec; // A file spec to use for opening after fork or posix_spawn }; } // namespace lldb_private diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h index d5ed81956475..d8e5ada6c96f 100644 --- a/include/lldb/Target/LanguageRuntime.h +++ b/include/lldb/Target/LanguageRuntime.h @@ -34,6 +34,9 @@ class LanguageRuntime : static LanguageRuntime* FindPlugin (Process *process, lldb::LanguageType language); + + static void + InitializeCommands (CommandObject* parent); virtual lldb::LanguageType GetLanguageType () const = 0; @@ -80,16 +83,27 @@ class LanguageRuntime : static lldb::BreakpointSP CreateExceptionBreakpoint (Target &target, - lldb::LanguageType language, + lldb::LanguageType language, bool catch_bp, bool throw_bp, bool is_internal = false); - + + static Breakpoint::BreakpointPreconditionSP + CreateExceptionPrecondition (lldb::LanguageType language, + bool catch_bp, + bool throw_bp); + static lldb::LanguageType GetLanguageTypeFromString (const char *string); static const char * GetNameForLanguageType (lldb::LanguageType language); + + static void + PrintAllLanguages (Stream &s, const char *prefix, const char *suffix); + + static bool + LanguageIsCPlusPlus (lldb::LanguageType language); Process * GetProcess() @@ -109,6 +123,18 @@ class LanguageRuntime : { return false; } + + virtual bool + IsRuntimeSupportValue (ValueObject& valobj) + { + return false; + } + + virtual void + ModulesDidLoad (const ModuleList &module_list) + { + return; + } protected: //------------------------------------------------------------------ diff --git a/include/lldb/Target/Memory.h b/include/lldb/Target/Memory.h index 568bbcdf2f7c..bf1cc1878784 100644 --- a/include/lldb/Target/Memory.h +++ b/include/lldb/Target/Memory.h @@ -52,7 +52,7 @@ namespace lldb_private { uint32_t GetMemoryCacheLineSize() const { - return m_cache_line_byte_size ; + return m_L2_cache_line_byte_size ; } void @@ -61,17 +61,26 @@ namespace lldb_private { bool RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size); + // Allow external sources to populate data into the L1 memory cache + void + AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len); + + void + AddL1CacheData(lldb::addr_t addr, const lldb::DataBufferSP &data_buffer_sp); + protected: typedef std::map BlockMap; typedef RangeArray InvalidRanges; + typedef Range AddrRange; //------------------------------------------------------------------ // Classes that inherit from MemoryCache can see and modify these //------------------------------------------------------------------ - Process &m_process; - uint32_t m_cache_line_byte_size; Mutex m_mutex; - BlockMap m_cache; + BlockMap m_L1_cache; // A first level memory cache whose chunk sizes vary that will be used only if the memory read fits entirely in a chunk + BlockMap m_L2_cache; // A memory cache of fixed size chinks (m_L2_cache_line_byte_size bytes in size each) InvalidRanges m_invalid_ranges; + Process &m_process; + uint32_t m_L2_cache_line_byte_size; private: DISALLOW_COPY_AND_ASSIGN (MemoryCache); }; diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h index 42a391478e3e..88874c767a1b 100644 --- a/include/lldb/Target/ObjCLanguageRuntime.h +++ b/include/lldb/Target/ObjCLanguageRuntime.h @@ -26,6 +26,8 @@ #include "lldb/Symbol/Type.h" #include "lldb/Target/LanguageRuntime.h" +class CommandObjectObjC_ClassTable_Dump; + namespace lldb_private { class ClangUtilityFunction; @@ -289,6 +291,48 @@ class ObjCLanguageRuntime : protected: std::unique_ptr m_scratch_ast_ctx_ap; }; + + class ObjCExceptionPrecondition : public Breakpoint::BreakpointPrecondition + { + public: + ObjCExceptionPrecondition(); + + virtual ~ObjCExceptionPrecondition() {} + + bool EvaluatePrecondition(StoppointCallbackContext &context) override; + void DescribePrecondition(Stream &stream, lldb::DescriptionLevel level) override; + Error ConfigurePrecondition(Args &args) override; + + protected: + void AddClassName(const char *class_name); + + private: + std::unordered_set m_class_names; + }; + + class TaggedPointerVendor + { + public: + virtual bool + IsPossibleTaggedPointer (lldb::addr_t ptr) = 0; + + virtual ObjCLanguageRuntime::ClassDescriptorSP + GetClassDescriptor (lldb::addr_t ptr) = 0; + + virtual + ~TaggedPointerVendor () { } + protected: + TaggedPointerVendor () = default; + + private: + DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor); + }; + + virtual TaggedPointerVendor* + GetTaggedPointerVendor () + { + return nullptr; + } typedef std::shared_ptr EncodingToTypeSP; @@ -313,8 +357,8 @@ class ObjCLanguageRuntime : virtual ~ObjCLanguageRuntime(); - virtual lldb::LanguageType - GetLanguageType () const + lldb::LanguageType + GetLanguageType () const override { return lldb::eLanguageTypeObjC; } @@ -515,10 +559,10 @@ class ObjCLanguageRuntime : m_negative_complete_class_cache.clear(); } - virtual bool + bool GetTypeBitSize (const ClangASTType& clang_type, - uint64_t &size); - + uint64_t &size) override; + protected: //------------------------------------------------------------------ // Classes that inherit from ObjCLanguageRuntime can see and modify these @@ -645,6 +689,14 @@ class ObjCLanguageRuntime : ISAToDescriptorIterator GetDescriptorIterator (const ConstString &name); + friend class ::CommandObjectObjC_ClassTable_Dump; + + std::pair + GetDescriptorIteratorPair (bool update_if_needed = true); + + void + ReadObjCLibraryIfNeeded (const ModuleList &module_list); + DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime); }; diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h index f4596bd00f0b..8f89e9b3cf5f 100644 --- a/include/lldb/Target/Platform.h +++ b/include/lldb/Target/Platform.h @@ -12,7 +12,9 @@ // C Includes // C++ Includes +#include #include +#include #include #include @@ -23,7 +25,9 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Core/UserSettingsController.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/Mutex.h" // TODO pull NativeDelegate class out of NativeProcessProtocol so we @@ -32,6 +36,34 @@ namespace lldb_private { +class ModuleCache; + + enum MmapFlags { + eMmapFlagsPrivate = 1, + eMmapFlagsAnon = 2 + }; + + class PlatformProperties : public Properties + { + public: + static ConstString + GetSettingName (); + + PlatformProperties(); + + bool + GetUseModuleCache () const; + bool + SetUseModuleCache (bool use_module_cache); + + FileSpec + GetModuleCacheDirectory () const; + bool + SetModuleCacheDirectory (const FileSpec& dir_spec); + }; + + typedef std::shared_ptr PlatformPropertiesSP; + //---------------------------------------------------------------------- /// @class Platform Platform.h "lldb/Target/Platform.h" /// @brief A plug-in interface definition class for debug platform that @@ -49,9 +81,17 @@ namespace lldb_private { public PluginInterface { public: + static void + Initialize (); + + static void + Terminate (); + + static const PlatformPropertiesSP & + GetGlobalPlatformProperties (); //------------------------------------------------------------------ - /// Get the native host platform plug-in. + /// Get the native host platform plug-in. /// /// There should only be one of these for each host that LLDB runs /// upon that should be statically compiled in and registered using @@ -277,15 +317,15 @@ namespace lldb_private { { return ArchSpec(); // Return an invalid architecture } - - virtual ConstString + + virtual FileSpec GetRemoteWorkingDirectory() { return m_working_dir; } virtual bool - SetRemoteWorkingDirectory(const ConstString &path); + SetRemoteWorkingDirectory(const FileSpec &working_dir); virtual const char * GetUserName (uint32_t uid); @@ -336,14 +376,20 @@ namespace lldb_private { LocateExecutableScriptingResources (Target *target, Module &module, Stream* feedback_stream); - + virtual Error - GetSharedModule (const ModuleSpec &module_spec, + GetSharedModule (const ModuleSpec &module_spec, + Process* process, lldb::ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); + virtual bool + GetModuleSpec (const FileSpec& module_file_spec, + const ArchSpec& arch, + ModuleSpec &module_spec); + virtual Error ConnectRemote (Args& args); @@ -379,6 +425,16 @@ namespace lldb_private { virtual Error LaunchProcess (ProcessLaunchInfo &launch_info); + //------------------------------------------------------------------ + /// Perform expansion of the command-line for this launch info + /// This can potentially involve wildcard expansion + // environment variable replacement, and whatever other + // argument magic the platform defines as part of its typical + // user experience + //------------------------------------------------------------------ + virtual Error + ShellExpandArguments (ProcessLaunchInfo &launch_info); + //------------------------------------------------------------------ /// Kill process on a platform. //------------------------------------------------------------------ @@ -577,12 +633,12 @@ namespace lldb_private { virtual void AddClangModuleCompilationOptions (Target *target, std::vector &options); - ConstString - GetWorkingDirectory (); - + FileSpec + GetWorkingDirectory(); + bool - SetWorkingDirectory (const ConstString &path); - + SetWorkingDirectory(const FileSpec &working_dir); + // There may be modules that we don't want to find by default for operations like "setting breakpoint by name". // The platform will return "true" from this call if the passed in module happens to be one of these. @@ -593,13 +649,13 @@ namespace lldb_private { } virtual Error - MakeDirectory (const char *path, uint32_t permissions); - - virtual Error - GetFilePermissions (const char *path, uint32_t &file_permissions); + MakeDirectory(const FileSpec &file_spec, uint32_t permissions); virtual Error - SetFilePermissions (const char *path, uint32_t file_permissions); + GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions); + + virtual Error + SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions); virtual lldb::user_id_t OpenFile (const FileSpec& file_spec, @@ -656,8 +712,8 @@ namespace lldb_private { uint32_t gid = UINT32_MAX); virtual Error - CreateSymlink (const char *src, // The name of the link is in src - const char *dst);// The symlink points to dst + CreateSymlink(const FileSpec &src, // The name of the link is in src + const FileSpec &dst); // The symlink points to dst //---------------------------------------------------------------------- /// Install a file or directory to the remote system. @@ -693,7 +749,10 @@ namespace lldb_private { GetFileExists (const lldb_private::FileSpec& file_spec); virtual Error - Unlink (const char *path); + Unlink(const FileSpec &file_spec); + + virtual uint64_t + ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags); virtual bool GetSupportsRSync () @@ -774,13 +833,13 @@ namespace lldb_private { } virtual lldb_private::Error - RunShellCommand (const char *command, // Shouldn't be NULL - const char *working_dir, // Pass NULL to use the current working directory - int *status_ptr, // Pass NULL if you don't want the process exit status - int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit - std::string *command_output, // Pass NULL if you don't want the command output - uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish - + RunShellCommand(const char *command, // Shouldn't be NULL + const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory + int *status_ptr, // Pass NULL if you don't want the process exit status + int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit + std::string *command_output, // Pass NULL if you don't want the command output + uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish + virtual void SetLocalCacheDirectory (const char* local); @@ -950,7 +1009,7 @@ namespace lldb_private { bool m_system_arch_set_while_connected; ConstString m_sdk_sysroot; // the root location of where the SDK files are all located ConstString m_sdk_build; - ConstString m_working_dir; // The working directory which is used when installing modules that have no install path set + 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; uint32_t m_major_os_version; @@ -972,6 +1031,7 @@ namespace lldb_private { std::string m_local_cache_directory; std::vector m_trap_handlers; bool m_calculated_trap_handlers; + const std::unique_ptr m_module_cache; //------------------------------------------------------------------ /// Ask the Platform subclass to fill in the list of trap handler names @@ -1074,7 +1134,45 @@ namespace lldb_private { m_gid_map.clear(); } + Error + GetCachedExecutable (ModuleSpec &module_spec, + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + Platform &remote_platform); + + virtual Error + DownloadModuleSlice (const FileSpec& src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec& dst_file_spec); + + virtual const char * + GetCacheHostname (); + private: + typedef std::function ModuleResolver; + + Error + GetRemoteSharedModule (const ModuleSpec &module_spec, + Process* process, + lldb::ModuleSP &module_sp, + const ModuleResolver &module_resolver, + bool *did_create_ptr); + + bool + GetCachedSharedModule (const ModuleSpec& module_spec, + lldb::ModuleSP &module_sp, + bool *did_create_ptr); + + Error + LoadCachedExecutable (const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + Platform &remote_platform); + + FileSpec + GetModuleCacheRoot (); + DISALLOW_COPY_AND_ASSIGN (Platform); }; diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index 6608391b94fd..db0f0cfa028b 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -28,34 +28,26 @@ #include "lldb/Core/Communication.h" #include "lldb/Core/Error.h" #include "lldb/Core/Event.h" -#include "lldb/Core/RangeMap.h" -#include "lldb/Core/StringList.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Breakpoint/BreakpointSiteList.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/IRDynamicChecks.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/Host.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ProcessRunLock.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/Options.h" #include "lldb/Target/ExecutionContextScope.h" -#include "lldb/Target/JITLoaderList.h" #include "lldb/Target/Memory.h" -#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/ProcessInfo.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/QueueList.h" #include "lldb/Target/ThreadList.h" -#include "lldb/Target/UnixSignals.h" -#include "lldb/Utility/PseudoTerminal.h" #include "lldb/Target/InstrumentationRuntime.h" namespace lldb_private { +template +struct Range; + //---------------------------------------------------------------------- // ProcessProperties //---------------------------------------------------------------------- @@ -693,7 +685,20 @@ friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs); else m_running_user_expression--; } - + + void + SetStopEventForLastNaturalStopID (lldb::EventSP event_sp) + { + m_last_natural_stop_event = event_sp; + } + + lldb::EventSP GetStopEventForStopID (uint32_t stop_id) const + { + if (stop_id == m_last_natural_stop_id) + return m_last_natural_stop_event; + return lldb::EventSP(); + } + private: uint32_t m_stop_id; uint32_t m_last_natural_stop_id; @@ -701,6 +706,7 @@ friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs); uint32_t m_memory_id; uint32_t m_last_user_expression_resume; uint32_t m_running_user_expression; + lldb::EventSP m_last_natural_stop_event; }; inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs) { @@ -812,11 +818,12 @@ class Process : virtual const ConstString & GetFlavor () const; - const lldb::ProcessSP & + lldb::ProcessSP GetProcessSP() const { - return m_process_sp; + return m_process_wp.lock(); } + lldb::StateType GetState() const { @@ -911,7 +918,7 @@ class Process : m_restarted_reasons.push_back(reason); } - lldb::ProcessSP m_process_sp; + lldb::ProcessWP m_process_wp; lldb::StateType m_state; std::vector m_restarted_reasons; bool m_restarted; // For "eStateStopped" events, this is true if the target was automatically restarted. @@ -1129,6 +1136,22 @@ class Process : virtual const lldb::DataBufferSP GetAuxvData(); + //------------------------------------------------------------------ + /// Sometimes processes know how to retrieve and load shared libraries. + /// This is normally done by DynamicLoader plug-ins, but sometimes the + /// connection to the process allows retrieving this information. The + /// dynamic loader plug-ins can use this function if they can't + /// determine the current shared library load state. + /// + /// @return + /// The number of shared libraries that were loaded + //------------------------------------------------------------------ + virtual size_t + LoadModules () + { + return 0; + } + protected: virtual JITLoaderList & GetJITLoaders (); @@ -1351,11 +1374,19 @@ class Process : /// This function is not meant to be overridden by Process /// subclasses. /// + /// @param[in] force_kill + /// Whether lldb should force a kill (instead of a detach) from + /// the inferior process. Normally if lldb launched a binary and + /// Destory is called, lldb kills it. If lldb attached to a + /// running process and Destory is called, lldb detaches. If + /// this behavior needs to be over-ridden, this is the bool that + /// can be used. + /// /// @return /// Returns an error object. //------------------------------------------------------------------ Error - Destroy(); + Destroy(bool force_kill); //------------------------------------------------------------------ /// Sends a process a UNIX signal \a signal. @@ -1370,18 +1401,10 @@ class Process : Signal (int signal); void - SetUnixSignals (const UnixSignalsSP &signals_sp) - { - assert (signals_sp && "null signals_sp"); - m_unix_signals_sp = signals_sp; - } + SetUnixSignals (const UnixSignalsSP &signals_sp); UnixSignals & - GetUnixSignals () - { - assert (m_unix_signals_sp && "null m_unix_signals_sp"); - return *m_unix_signals_sp; - } + GetUnixSignals (); //================================================================== // Plug-in Process Control Overrides @@ -1439,24 +1462,6 @@ class Process : return error; } - //------------------------------------------------------------------ - /// Attach to an existing process using a process ID. - /// - /// @param[in] pid - /// The process ID that we should attempt to attach to. - /// - /// @return - /// Returns \a pid if attaching was successful, or - /// LLDB_INVALID_PROCESS_ID if attaching fails. - //------------------------------------------------------------------ - virtual Error - DoAttachToProcessWithID (lldb::pid_t pid) - { - Error error; - error.SetErrorStringWithFormat("error: %s does not support attaching to a process by pid", GetPluginName().GetCString()); - return error; - } - //------------------------------------------------------------------ /// Attach to an existing process using a process ID. /// @@ -1468,8 +1473,9 @@ class Process : /// will return the uid to attach as. /// /// @return - /// Returns \a pid if attaching was successful, or - /// LLDB_INVALID_PROCESS_ID if attaching fails. + /// Returns a successful Error attaching was successful, or + /// an appropriate (possibly platform-specific) error code if + /// attaching fails. /// hanming : need flag //------------------------------------------------------------------ virtual Error @@ -1491,7 +1497,9 @@ class Process : /// will return the uid to attach as. /// /// @return - /// Returns an error object. + /// Returns a successful Error attaching was successful, or + /// an appropriate (possibly platform-specific) error code if + /// attaching fails. //------------------------------------------------------------------ virtual Error DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info) @@ -1870,7 +1878,13 @@ class Process : void SendAsyncInterrupt (); - void + //------------------------------------------------------------------ + // Notify this process class that modules got loaded. + // + // If subclasses override this method, they must call this version + // before doing anything in the subclass version of the function. + //------------------------------------------------------------------ + virtual void ModulesDidLoad (ModuleList &module_list); protected: @@ -1961,11 +1975,17 @@ class Process : } uint32_t - GetLastNaturalStopID() + GetLastNaturalStopID() const { return m_mod_id.GetLastNaturalStopID(); } - + + lldb::EventSP + GetStopEventForStopID (uint32_t stop_id) const + { + return m_mod_id.GetStopEventForStopID(stop_id); + } + //------------------------------------------------------------------ /// Set accessor for the process exit status (return code). /// @@ -2399,33 +2419,8 @@ class Process : /// Returns true if it was able to determine the attributes of the /// memory region. False if not. //------------------------------------------------------------------ - virtual bool - GetLoadAddressPermissions (lldb::addr_t load_addr, uint32_t &permissions) - { - MemoryRegionInfo range_info; - permissions = 0; - Error error (GetMemoryRegionInfo (load_addr, range_info)); - if (!error.Success()) - return false; - if (range_info.GetReadable() == MemoryRegionInfo::eDontKnow - || range_info.GetWritable() == MemoryRegionInfo::eDontKnow - || range_info.GetExecutable() == MemoryRegionInfo::eDontKnow) - { - return false; - } - - if (range_info.GetReadable() == MemoryRegionInfo::eYes) - permissions |= lldb::ePermissionsReadable; - - if (range_info.GetWritable() == MemoryRegionInfo::eYes) - permissions |= lldb::ePermissionsWritable; - - if (range_info.GetExecutable() == MemoryRegionInfo::eYes) - permissions |= lldb::ePermissionsExecutable; - - return true; - } + GetLoadAddressPermissions (lldb::addr_t load_addr, uint32_t &permissions); //------------------------------------------------------------------ /// Determines whether executing JIT-compiled code in this process @@ -2758,6 +2753,11 @@ class Process : Listener *hijack_listener = NULL, Stream *stream = NULL); + uint32_t + GetIOHandlerID () const + { + return m_iohandler_sync.GetValue(); + } //-------------------------------------------------------------------------------------- /// Waits for the process state to be running within a given msec timeout. @@ -2768,14 +2768,9 @@ class Process : /// @param[in] timeout_msec /// The maximum time length to wait for the process to transition to the /// eStateRunning state, specified in milliseconds. - /// - /// @return - /// true if successfully signalled that process started and IOHandler pushes, false - /// if it timed out. //-------------------------------------------------------------------------------------- - bool - SyncIOHandler (uint64_t timeout_msec); - + void + SyncIOHandler (uint32_t iohandler_id, uint64_t timeout_msec); lldb::StateType WaitForStateChangedEvents (const TimeValue *timeout, @@ -2906,10 +2901,7 @@ class Process : return m_dynamic_checkers_ap.get(); } - void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers) - { - m_dynamic_checkers_ap.reset(dynamic_checkers); - } + void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers); //------------------------------------------------------------------ /// Call this to set the lldb in the mode where it breaks on new thread @@ -3010,17 +3002,10 @@ class Process : void ClearPreResumeActions (); - + ProcessRunLock & - GetRunLock () - { - if (m_private_state_thread.EqualsThread(Host::GetCurrentThread())) - return m_private_run_lock; - else - return m_public_run_lock; - } + GetRunLock (); -public: virtual Error SendEventData(const char *data) { @@ -3034,6 +3019,51 @@ class Process : lldb::InstrumentationRuntimeSP GetInstrumentationRuntime(lldb::InstrumentationRuntimeType type); + //------------------------------------------------------------------ + /// Try to fetch the module specification for a module with the + /// given file name and architecture. Process sub-classes have to + /// override this method if they support platforms where the + /// Platform object can't get the module spec for all module. + /// + /// @param[in] module_file_spec + /// The file name of the module to get specification for. + /// + /// @param[in] arch + /// The architecture of the module to get specification for. + /// + /// @param[out] module_spec + /// The fetched module specification if the return value is + /// \b true, unchanged otherwise. + /// + /// @return + /// Returns \b true if the module spec fetched successfully, + /// \b false otherwise. + //------------------------------------------------------------------ + virtual bool + GetModuleSpec(const FileSpec& module_file_spec, const ArchSpec& arch, ModuleSpec &module_spec); + + //------------------------------------------------------------------ + /// Try to find the load address of a file. + /// The load address is defined as the address of the first memory + /// region what contains data mapped from the specified file. + /// + /// @param[in] file + /// The name of the file whose load address we are looking for + /// + /// @param[out] is_loaded + /// \b True if the file is loaded into the memory and false + /// otherwise. + /// + /// @param[out] load_addr + /// The load address of the file if it is loaded into the + /// processes address space, LLDB_INVALID_ADDRESS otherwise. + //------------------------------------------------------------------ + virtual Error + GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) + { + return Error("Not supported"); + } + protected: //------------------------------------------------------------------ @@ -3150,7 +3180,7 @@ class Process : Broadcaster m_private_state_control_broadcaster; // This is the control broadcaster, used to pause, resume & stop the private state thread. Listener m_private_state_listener; // This is the listener for the private state thread. Predicate m_private_state_control_wait; /// This Predicate is used to signal that a control operation is complete. - HostThread m_private_state_thread; // Thread ID for the thread that watches internal state events + HostThread m_private_state_thread; ///< Thread ID for the thread that watches internal state events ProcessModID m_mod_id; ///< Tracks the state of the process over stops and other alterations. uint32_t m_process_unique_id; ///< Each lldb_private::Process class that is created gets a unique integer ID that increments with each new instance uint32_t m_thread_index_id; ///< Each thread is created with a 1 based index that won't get re-used. @@ -3170,22 +3200,22 @@ class Process : std::vector m_image_tokens; Listener &m_listener; BreakpointSiteList m_breakpoint_site_list; ///< This is the list of breakpoint locations we intend to insert in the target. - std::unique_ptr m_dyld_ap; - std::unique_ptr m_jit_loaders_ap; - std::unique_ptr m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use. - std::unique_ptr m_os_ap; - std::unique_ptr m_system_runtime_ap; + lldb::DynamicLoaderUP m_dyld_ap; + lldb::JITLoaderListUP m_jit_loaders_ap; + lldb::DynamicCheckerFunctionsUP m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use. + lldb::OperatingSystemUP m_os_ap; + lldb::SystemRuntimeUP m_system_runtime_ap; UnixSignalsSP 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; Mutex m_stdio_communication_mutex; - bool m_stdio_disable; /// Remember process launch setting + bool m_stdin_forward; /// Remember if stdin must be forwarded to remote debug server std::string m_stdout_data; std::string m_stderr_data; Mutex m_profile_data_comm_mutex; std::vector m_profile_data; - Predicate m_iohandler_sync; + Predicate m_iohandler_sync; MemoryCache m_memory_cache; AllocatedMemoryCache m_allocated_memory_cache; bool m_should_detach; /// Should we detach if the process object goes away with an explicit call to Kill or Detach? @@ -3199,7 +3229,8 @@ class Process : ArchSpec::StopInfoOverrideCallbackType m_stop_info_override_callback; bool m_currently_handling_do_on_removals; bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check. - bool m_finalize_called; + bool m_finalizing; // This is set at the beginning of Process::Finalize() to stop functions from looking up or creating things during a finalize call + bool m_finalize_called; // This is set at the end of Process::Finalize() bool m_clear_thread_plans_on_stop; bool m_force_next_event_delivery; lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent. @@ -3225,7 +3256,7 @@ class Process : SetPrivateState (lldb::StateType state); bool - StartPrivateStateThread (bool force = false); + StartPrivateStateThread (bool is_secondary_thread = false); void StopPrivateStateThread (); @@ -3236,11 +3267,22 @@ class Process : void ResumePrivateStateThread (); + struct PrivateStateThreadArgs + { + Process *process; + bool is_secondary_thread; + }; + 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-called function on the primary + // private state thread. + lldb::thread_result_t - RunPrivateStateThread (); + RunPrivateStateThread (bool is_secondary_thread); void HandlePrivateEvent (lldb::EventSP &event_sp); @@ -3285,6 +3327,12 @@ class Process : bool ProcessIOHandlerIsActive (); + + bool + ProcessIOHandlerExists () const + { + return static_cast(m_process_input_reader); + } Error HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp); diff --git a/include/lldb/Target/ProcessInfo.h b/include/lldb/Target/ProcessInfo.h index 0570cfc98651..1539e043d6fc 100644 --- a/include/lldb/Target/ProcessInfo.h +++ b/include/lldb/Target/ProcessInfo.h @@ -107,7 +107,7 @@ namespace lldb_private } void - SetArchitecture (ArchSpec arch) + SetArchitecture (const ArchSpec& arch) { m_arch = arch; } diff --git a/include/lldb/Target/ProcessLaunchInfo.h b/include/lldb/Target/ProcessLaunchInfo.h index 897704488e5f..92a3ed40736d 100644 --- a/include/lldb/Target/ProcessLaunchInfo.h +++ b/include/lldb/Target/ProcessLaunchInfo.h @@ -36,11 +36,11 @@ namespace lldb_private ProcessLaunchInfo (); - ProcessLaunchInfo (const char *stdin_path, - const char *stdout_path, - const char *stderr_path, - const char *working_directory, - uint32_t launch_flags); + ProcessLaunchInfo(const FileSpec &stdin_file_spec, + const FileSpec &stdout_file_spec, + const FileSpec &stderr_file_spec, + const FileSpec &working_dir, + uint32_t launch_flags); void AppendFileAction (const FileAction &info) @@ -55,7 +55,8 @@ namespace lldb_private AppendDuplicateFileAction (int fd, int dup_fd); bool - AppendOpenFileAction (int fd, const char *path, bool read, bool write); + AppendOpenFileAction(int fd, const FileSpec &file_spec, + bool read, bool write); bool AppendSuppressFileAction (int fd, bool read, bool write); @@ -88,17 +89,11 @@ namespace lldb_private return m_flags; } - const char * - GetWorkingDirectory () const; + const FileSpec & + GetWorkingDirectory() const; void - SetWorkingDirectory (const char *working_dir); - - void - SwapWorkingDirectory (std::string &working_dir) - { - m_working_dir.swap (working_dir); - } + SetWorkingDirectory(const FileSpec &working_dir); const char * GetProcessPluginName () const; @@ -132,6 +127,15 @@ namespace lldb_private void SetLaunchInSeparateProcessGroup (bool separate); + + bool + GetShellExpandArguments () const + { + return m_flags.Test(lldb::eLaunchFlagShellExpandArguments); + } + + void + SetShellExpandArguments (bool expand); void Clear (); @@ -229,7 +233,7 @@ namespace lldb_private } protected: - std::string m_working_dir; + FileSpec m_working_dir; std::string m_plugin_name; FileSpec m_shell; Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags diff --git a/include/lldb/Target/SectionLoadHistory.h b/include/lldb/Target/SectionLoadHistory.h index 50dcfd3cc870..ddf46a1861ca 100644 --- a/include/lldb/Target/SectionLoadHistory.h +++ b/include/lldb/Target/SectionLoadHistory.h @@ -23,7 +23,7 @@ namespace lldb_private { class SectionLoadHistory { public: - enum { + enum : unsigned { // Pass eStopIDNow to any function that takes a stop ID to get // the current value. eStopIDNow = UINT32_MAX diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h index e0d029bcc956..d09900f7637d 100644 --- a/include/lldb/Target/StopInfo.h +++ b/include/lldb/Target/StopInfo.h @@ -116,6 +116,12 @@ class StopInfo else m_description.clear(); } + + virtual bool + IsValidForOperatingSystemThread (Thread &thread) + { + return true; + } // Sometimes the thread plan logic will know that it wants a given stop to stop or not, // regardless of what the ordinary logic for that StopInfo would dictate. The main example @@ -158,7 +164,7 @@ class StopInfo CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id); static lldb::StopInfoSP - CreateStopReasonWithSignal (Thread &thread, int signo); + CreateStopReasonWithSignal (Thread &thread, int signo, const char *description = nullptr); static lldb::StopInfoSP CreateStopReasonToTrace (Thread &thread); diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h index a33734fd5b63..427f68e4c5d4 100644 --- a/include/lldb/Target/Target.h +++ b/include/lldb/Target/Target.h @@ -18,24 +18,15 @@ // Project includes #include "lldb/lldb-public.h" #include "lldb/Breakpoint/BreakpointList.h" -#include "lldb/Breakpoint/BreakpointLocationCollection.h" #include "lldb/Breakpoint/WatchpointList.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Disassembler.h" -#include "lldb/Core/Event.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/UserSettingsController.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Interpreter/Args.h" -#include "lldb/Interpreter/OptionValueBoolean.h" -#include "lldb/Interpreter/OptionValueEnumeration.h" -#include "lldb/Interpreter/OptionValueFileSpec.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/PathMappingList.h" +#include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/SectionLoadHistory.h" namespace lldb_private { @@ -73,9 +64,15 @@ class TargetProperties : public Properties void SetDefaultArchitecture (const ArchSpec& arch); + bool + GetMoveToNearestCode () const; + lldb::DynamicValueType GetPreferDynamicValue() const; - + + bool + SetPreferDynamicValue (lldb::DynamicValueType d); + bool GetDisableASLR () const; @@ -117,7 +114,10 @@ class TargetProperties : public Properties size_t GetEnvironmentAsArgs (Args &env) const; - + + void + SetEnvironmentFromArgs (const Args &env); + bool GetSkipPrologue() const; @@ -130,6 +130,12 @@ class TargetProperties : public Properties FileSpecList & GetDebugFileSearchPaths (); + FileSpecList & + GetClangModuleSearchPaths (); + + bool + GetEnableAutoImportClangModules () const; + bool GetEnableSyntheticValue () const; @@ -189,9 +195,46 @@ class TargetProperties : public Properties void SetUserSpecifiedTrapHandlerNames (const Args &args); -}; -typedef std::shared_ptr TargetPropertiesSP; + bool + GetNonStopModeEnabled () const; + + void + SetNonStopModeEnabled (bool b); + + bool + GetDisplayRuntimeSupportValues () const; + + void + SetDisplayRuntimeSupportValues (bool b); + + const ProcessLaunchInfo & + GetProcessLaunchInfo(); + + void + SetProcessLaunchInfo(const ProcessLaunchInfo &launch_info); + +private: + //------------------------------------------------------------------ + // Callbacks for m_launch_info. + //------------------------------------------------------------------ + static void Arg0ValueChangedCallback(void *target_property_ptr, OptionValue *); + static void RunArgsValueChangedCallback(void *target_property_ptr, OptionValue *); + static void EnvVarsValueChangedCallback(void *target_property_ptr, OptionValue *); + static void InheritEnvValueChangedCallback(void *target_property_ptr, OptionValue *); + static void InputPathValueChangedCallback(void *target_property_ptr, OptionValue *); + static void OutputPathValueChangedCallback(void *target_property_ptr, OptionValue *); + static void ErrorPathValueChangedCallback(void *target_property_ptr, OptionValue *); + static void DetachOnErrorValueChangedCallback(void *target_property_ptr, OptionValue *); + static void DisableASLRValueChangedCallback(void *target_property_ptr, OptionValue *); + static void DisableSTDIOValueChangedCallback(void *target_property_ptr, OptionValue *); + +private: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + ProcessLaunchInfo m_launch_info; +}; class EvaluateExpressionOptions { @@ -200,19 +243,20 @@ class EvaluateExpressionOptions EvaluateExpressionOptions() : m_execution_policy(eExecutionPolicyOnlyWhenNeeded), m_language (lldb::eLanguageTypeUnknown), - m_coerce_to_id(false), - m_unwind_on_error(true), + m_prefix (), // A prefix specific to this expression that is added after the prefix from the settings (if any) + m_coerce_to_id (false), + m_unwind_on_error (true), m_ignore_breakpoints (false), - m_keep_in_memory(false), - m_try_others(true), - m_stop_others(true), - m_debug(false), - m_trap_exceptions(true), - m_generate_debug_info(false), - m_result_is_internal(false), - m_use_dynamic(lldb::eNoDynamicValues), - m_timeout_usec(default_timeout), - m_one_thread_timeout_usec(0), + m_keep_in_memory (false), + m_try_others (true), + m_stop_others (true), + m_debug (false), + m_trap_exceptions (true), + m_generate_debug_info (false), + m_result_is_internal (false), + m_use_dynamic (lldb::eNoDynamicValues), + m_timeout_usec (default_timeout), + m_one_thread_timeout_usec (0), m_cancel_callback (nullptr), m_cancel_callback_baton (nullptr) { @@ -247,7 +291,24 @@ class EvaluateExpressionOptions { return m_coerce_to_id; } - + + const char * + GetPrefix () const + { + if (m_prefix.empty()) + return NULL; + return m_prefix.c_str(); + } + + void + SetPrefix (const char *prefix) + { + if (prefix && prefix[0]) + m_prefix = prefix; + else + m_prefix.clear(); + } + void SetCoerceToId (bool coerce = true) { @@ -419,6 +480,7 @@ class EvaluateExpressionOptions private: ExecutionPolicy m_execution_policy; lldb::LanguageType m_language; + std::string m_prefix; bool m_coerce_to_id; bool m_unwind_on_error; bool m_ignore_breakpoints; @@ -474,35 +536,49 @@ class Target : class TargetEventData : public EventData { public: + TargetEventData (const lldb::TargetSP &target_sp); + + TargetEventData (const lldb::TargetSP &target_sp, const ModuleList &module_list); + + virtual + ~TargetEventData(); static const ConstString & GetFlavorString (); virtual const ConstString & - GetFlavor () const; + GetFlavor () const + { + return TargetEventData::GetFlavorString (); + } - TargetEventData (const lldb::TargetSP &new_target_sp); - - lldb::TargetSP & - GetTarget() + virtual void + Dump (Stream *s) const; + + static const TargetEventData * + GetEventDataFromEvent (const Event *event_ptr); + + static lldb::TargetSP + GetTargetFromEvent (const Event *event_ptr); + + static ModuleList + GetModuleListFromEvent (const Event *event_ptr); + + const lldb::TargetSP & + GetTarget() const { return m_target_sp; } - virtual - ~TargetEventData(); - - virtual void - Dump (Stream *s) const; - - static const lldb::TargetSP - GetTargetFromEvent (const lldb::EventSP &event_sp); - - static const TargetEventData * - GetEventDataFromEvent (const Event *event_sp); + const ModuleList & + GetModuleList() const + { + return m_module_list; + } private: lldb::TargetSP m_target_sp; + ModuleList m_module_list; DISALLOW_COPY_AND_ASSIGN (TargetEventData); }; @@ -513,14 +589,14 @@ class Target : static void SettingsTerminate (); -// static lldb::UserSettingsControllerSP & -// GetSettingsController (); - static FileSpecList GetDefaultExecutableSearchPaths (); static FileSpecList GetDefaultDebugFileSearchPaths (); + + static FileSpecList + GetDefaultClangModuleSearchPaths (); static ArchSpec GetDefaultArchitecture (); @@ -539,7 +615,7 @@ class Target : // Settings accessors //---------------------------------------------------------------------- - static const TargetPropertiesSP & + static const lldb::TargetPropertiesSP & GetGlobalProperties(); @@ -617,7 +693,11 @@ class Target : Error Launch (ProcessLaunchInfo &launch_info, - Stream *stream); // Optional stream to receive first stop info + Stream *stream); // Optional stream to receive first stop info + + Error + Attach (ProcessAttachInfo &attach_info, + Stream *stream); // Optional stream to receive first stop info //------------------------------------------------------------------ // This part handles the breakpoints. @@ -646,7 +726,8 @@ class Target : LazyBool check_inlines, LazyBool skip_prologue, bool internal, - bool request_hardware); + bool request_hardware, + LazyBool move_to_nearest_code); // Use this to create breakpoint that matches regex against the source lines in files given in source_file_list: lldb::BreakpointSP @@ -654,7 +735,8 @@ class Target : const FileSpecList *source_file_list, RegularExpression &source_regex, bool internal, - bool request_hardware); + bool request_hardware, + LazyBool move_to_nearest_code); // Use this to create a breakpoint from a load address lldb::BreakpointSP @@ -681,7 +763,8 @@ class Target : // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL // When "skip_prologue is set to eLazyBoolCalculate, we use the current target - // setting, else we use the values passed in + // setting, else we use the values passed in. + // func_name_type_mask is or'ed values from the FunctionNameType enum. lldb::BreakpointSP CreateBreakpoint (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, @@ -692,11 +775,17 @@ class Target : bool request_hardware); lldb::BreakpointSP - CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal); + CreateExceptionBreakpoint (enum lldb::LanguageType language, + bool catch_bp, + bool throw_bp, + bool internal, + Args *additional_args = nullptr, + Error *additional_args_error = nullptr); // This is the same as the func_name breakpoint except that you can specify a vector of names. This is cheaper // than a regular expression breakpoint in the case where you just want to set a breakpoint on a set of names // you already know. + // func_name_type_mask is or'ed values from the FunctionNameType enum. lldb::BreakpointSP CreateBreakpoint (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, @@ -778,6 +867,9 @@ class Target : bool ClearAllWatchpointHitCounts (); + bool + ClearAllWatchpointHistoricValues (); + bool IgnoreAllWatchpoints (uint32_t ignore_count); @@ -1001,12 +1093,6 @@ class Target : bool ModuleIsExcludedForUnconstrainedSearches (const lldb::ModuleSP &module_sp); - ArchSpec & - GetArchitecture () - { - return m_arch; - } - const ArchSpec & GetArchitecture () const { @@ -1034,6 +1120,9 @@ class Target : bool SetArchitecture (const ArchSpec &arch_spec); + bool + MergeArchitecture (const ArchSpec &arch_spec); + Debugger & GetDebugger () { @@ -1182,10 +1271,7 @@ class Target : const EvaluateExpressionOptions& options = EvaluateExpressionOptions()); ClangPersistentVariables & - GetPersistentVariables() - { - return m_persistent_variables; - } + GetPersistentVariables(); //------------------------------------------------------------------ // Target Stop Hooks @@ -1223,10 +1309,7 @@ class Target : // Set the specifier. The stop hook will own the specifier, and is responsible for deleting it when we're done. void - SetSpecifier (SymbolContextSpecifier *specifier) - { - m_specifier_sp.reset (specifier); - } + SetSpecifier (SymbolContextSpecifier *specifier); SymbolContextSpecifier * GetSpecifier () @@ -1387,13 +1470,13 @@ class Target : lldb::ProcessSP m_process_sp; lldb::SearchFilterSP m_search_filter_sp; PathMappingList m_image_search_paths; - std::unique_ptr m_scratch_ast_context_ap; - std::unique_ptr m_scratch_ast_source_ap; - std::unique_ptr m_ast_importer_ap; - std::unique_ptr m_clang_modules_decl_vendor_ap; - ClangPersistentVariables m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser. + lldb::ClangASTContextUP m_scratch_ast_context_ap; + lldb::ClangASTSourceUP m_scratch_ast_source_ap; + lldb::ClangASTImporterUP m_ast_importer_ap; + lldb::ClangModulesDeclVendorUP m_clang_modules_decl_vendor_ap; + lldb::ClangPersistentVariablesUP m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser. - std::unique_ptr m_source_manager_ap; + lldb::SourceManagerUP m_source_manager_ap; typedef std::map StopHookCollection; StopHookCollection m_stop_hooks; diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h index 25c0c0e92bec..c6a3c8e9851a 100644 --- a/include/lldb/Target/Thread.h +++ b/include/lldb/Target/Thread.h @@ -205,22 +205,23 @@ class Thread : void SetState (lldb::StateType state); - lldb::StateType - GetResumeState () const - { - return m_resume_state; - } - - // This sets the "external resume state" of the thread. If the thread is suspended here, it should never - // get scheduled. Note that just because a thread is marked as "running" does not mean we will let it run in - // a given bit of process control. For instance "step" tries to stay on the selected thread it was issued on, - // which may involve suspending other threads temporarily. This temporary suspension is NOT reflected in the - // state set here and reported in GetResumeState. - // - // If you are just preparing all threads to run, you should not override the threads that are - // marked as suspended by the debugger. In that case, pass override_suspend = false. If you want - // to force the thread to run (e.g. the "thread continue" command, or are resetting the state - // (e.g. in SBThread::Resume()), then pass true to override_suspend. + //------------------------------------------------------------------ + /// Sets the USER resume state for this thread. If you set a thread to suspended with + /// this API, it won't take part in any of the arbitration for ShouldResume, and will stay + /// suspended even when other threads do get to run. + /// + /// N.B. This is not the state that is used internally by thread plans to implement + /// staying on one thread while stepping over a breakpoint, etc. The is the + /// TemporaryResume state, and if you are implementing some bit of strategy in the stepping + /// machinery you should be using that state and not the user resume state. + /// + /// If you are just preparing all threads to run, you should not override the threads that are + /// marked as suspended by the debugger. In that case, pass override_suspend = false. If you want + /// to force the thread to run (e.g. the "thread continue" command, or are resetting the state + /// (e.g. in SBThread::Resume()), then pass true to override_suspend. + /// @return + /// The User resume state for this thread. + //------------------------------------------------------------------ void SetResumeState (lldb::StateType state, bool override_suspend = false) { @@ -229,6 +230,21 @@ class Thread : m_resume_state = state; } + //------------------------------------------------------------------ + /// Gets the USER resume state for this thread. This is not the same as what + /// this thread is going to do for any particular step, however if this thread + /// returns eStateSuspended, then the process control logic will never allow this + /// thread to run. + /// + /// @return + /// The User resume state for this thread. + //------------------------------------------------------------------ + lldb::StateType + GetResumeState () const + { + return m_resume_state; + } + // This function is called on all the threads before "ShouldResume" and // "WillResume" in case a thread needs to change its state before the // ThreadList polls all the threads to figure out which ones actually @@ -1315,8 +1331,8 @@ class Thread : lldb::ProcessWP m_process_wp; ///< The process that owns this thread. lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that - 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 // the thread's m_stop_info_sp is current and you don't have to fetch it again + 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 const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread 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/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h index 67ac642de7bd..e40762c928b5 100644 --- a/include/lldb/Target/ThreadPlanCallUserExpression.h +++ b/include/lldb/Target/ThreadPlanCallUserExpression.h @@ -15,7 +15,6 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Expression/ClangUserExpression.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallFunction.h" @@ -31,7 +30,7 @@ class ThreadPlanCallUserExpression : public ThreadPlanCallFunction Address &function, llvm::ArrayRef args, const EvaluateExpressionOptions &options, - ClangUserExpression::ClangUserExpressionSP &user_expression_sp); + lldb::ClangUserExpressionSP &user_expression_sp); virtual ~ThreadPlanCallUserExpression (); @@ -62,12 +61,12 @@ class ThreadPlanCallUserExpression : public ThreadPlanCallFunction protected: private: - ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the - // User expression the initiated this ThreadPlan - // lives as long as the thread plan does. + lldb::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the + // User expression the initiated this ThreadPlan + // lives as long as the thread plan does. bool m_manage_materialization = false; - lldb::ClangExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization, - // then stuff the result expression variable here. + lldb::ClangExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization, + // then stuff the result expression variable here. DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression); }; diff --git a/include/lldb/Target/ThreadPlanPython.h b/include/lldb/Target/ThreadPlanPython.h index fa41af1915cd..ffcee018a5fb 100644 --- a/include/lldb/Target/ThreadPlanPython.h +++ b/include/lldb/Target/ThreadPlanPython.h @@ -16,6 +16,7 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Core/UserID.h" #include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" @@ -68,8 +69,8 @@ class ThreadPlanPython : public ThreadPlan GetPlanRunState (); private: - std::string m_class_name; - lldb::ScriptInterpreterObjectSP m_implementation_sp; + std::string m_class_name; + StructuredData::ObjectSP m_implementation_sp; DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython); }; diff --git a/include/lldb/Utility/ConvertEnum.h b/include/lldb/Utility/ConvertEnum.h new file mode 100644 index 000000000000..6d37484b0112 --- /dev/null +++ b/include/lldb/Utility/ConvertEnum.h @@ -0,0 +1,22 @@ +//===-- ConvertEnum.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLDB_UTILITY_CONVERTENUM_H +#define LLDB_UTILITY_CONVERTENUM_H + +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-enumerations.h" + +namespace lldb_private +{ + +const char *GetVoteAsCString(Vote vote); +const char *GetSectionTypeAsCString(lldb::SectionType sect_type); +} + +#endif diff --git a/include/lldb/Utility/JSON.h b/include/lldb/Utility/JSON.h new file mode 100644 index 000000000000..45ddb71b5e03 --- /dev/null +++ b/include/lldb/Utility/JSON.h @@ -0,0 +1,276 @@ +//===---------------------JSON.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_JSON_h_ +#define utility_JSON_h_ + +#include "lldb/Core/Stream.h" + +#include +#include +#include +#include +#include +#include + +#include "llvm/Support/Casting.h" + +namespace lldb_private { + class JSONValue + { + public: + virtual void + Write (Stream& s) = 0; + + typedef std::shared_ptr SP; + + enum class Kind + { + String, + Number, + True, + False, + Null, + Object, + Array + }; + + JSONValue (Kind k) : + m_kind(k) + {} + + Kind + GetKind() const + { + return m_kind; + } + + virtual + ~JSONValue () = default; + + private: + const Kind m_kind; + }; + + class JSONString : public JSONValue + { + public: + JSONString (); + JSONString (const char* s); + JSONString (const std::string& s); + + JSONString (const JSONString& s) = delete; + JSONString& + operator = (const JSONString& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + std::string + GetData () { return m_data; } + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::String; + } + + virtual + ~JSONString () = default; + + private: + + static std::string + json_string_quote_metachars (const std::string&); + + std::string m_data; + }; + + class JSONNumber : public JSONValue + { + public: + JSONNumber (); + JSONNumber (int64_t i); + + JSONNumber (const JSONNumber& s) = delete; + JSONNumber& + operator = (const JSONNumber& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + int64_t + GetData () { return m_data; } + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::Number; + } + + virtual + ~JSONNumber () = default; + + private: + int64_t m_data; + }; + + class JSONTrue : public JSONValue + { + public: + JSONTrue (); + + JSONTrue (const JSONTrue& s) = delete; + JSONTrue& + operator = (const JSONTrue& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::True; + } + + virtual + ~JSONTrue () = default; + }; + + class JSONFalse : public JSONValue + { + public: + JSONFalse (); + + JSONFalse (const JSONFalse& s) = delete; + JSONFalse& + operator = (const JSONFalse& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::False; + } + + virtual + ~JSONFalse () = default; + }; + + class JSONNull : public JSONValue + { + public: + JSONNull (); + + JSONNull (const JSONNull& s) = delete; + JSONNull& + operator = (const JSONNull& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::Null; + } + + virtual + ~JSONNull () = default; + }; + + class JSONObject : public JSONValue + { + public: + JSONObject (); + + JSONObject (const JSONObject& s) = delete; + JSONObject& + operator = (const JSONObject& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::Object; + } + + bool + SetObject (const std::string& key, + JSONValue::SP value); + + JSONValue::SP + GetObject (const std::string& key); + + virtual + ~JSONObject () = default; + + private: + typedef std::map Map; + typedef Map::iterator Iterator; + Map m_elements; + }; + + class JSONArray : public JSONValue + { + public: + JSONArray (); + + JSONArray (const JSONArray& s) = delete; + JSONArray& + operator = (const JSONArray& s) = delete; + + virtual void + Write (Stream& s); + + typedef std::shared_ptr SP; + + static bool classof(const JSONValue *V) + { + return V->GetKind() == JSONValue::Kind::Array; + } + + private: + typedef std::vector Vector; + typedef Vector::iterator Iterator; + typedef Vector::size_type Index; + typedef Vector::size_type Size; + + public: + bool + SetObject (Index i, + JSONValue::SP value); + + bool + AppendObject (JSONValue::SP value); + + JSONValue::SP + GetObject (Index i); + + Size + GetNumElements (); + + virtual + ~JSONArray () = default; + + Vector m_elements; + }; +} + +#endif // utility_ProcessStructReader_h_ diff --git a/include/lldb/Utility/LLDBAssert.h b/include/lldb/Utility/LLDBAssert.h new file mode 100644 index 000000000000..5ca252f20032 --- /dev/null +++ b/include/lldb/Utility/LLDBAssert.h @@ -0,0 +1,30 @@ +//===----------------- LLDBAssert.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_LLDBAssert_h_ +#define utility_LLDBAssert_h_ + +#include + +#ifdef LLDB_CONFIGURATION_DEBUG +#define lldbassert(x) assert(x) +#else +#define lldbassert(x) lldb_private::lldb_assert(x, #x, __FUNCTION__, __FILE__, __LINE__) +#endif + +namespace lldb_private { + void + lldb_assert (bool expression, + const char* expr_text, + const char* func, + const char* file, + unsigned int line); +} + +#endif // utility_LLDBAssert_h_ diff --git a/include/lldb/Utility/NameMatches.h b/include/lldb/Utility/NameMatches.h new file mode 100644 index 000000000000..5fe6565d06f9 --- /dev/null +++ b/include/lldb/Utility/NameMatches.h @@ -0,0 +1,19 @@ +//===-- NameMatches.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLDB_UTILITY_NAMEMATCHES_H +#define LLDB_UTILITY_NAMEMATCHES_H + +#include "lldb/lldb-private-enumerations.h" + +namespace lldb_private +{ +bool NameMatches(const char *name, NameMatchType match_type, const char *match); +} + +#endif diff --git a/include/lldb/Utility/PseudoTerminal.h b/include/lldb/Utility/PseudoTerminal.h index 6ee598cefe08..595b2fc19bfd 100644 --- a/include/lldb/Utility/PseudoTerminal.h +++ b/include/lldb/Utility/PseudoTerminal.h @@ -175,7 +175,7 @@ class PseudoTerminal /// occur. This can be NULL if no error status is desired. /// /// @return - /// @li \b true when the a master files descriptor is + /// @li \b true when the master files descriptor is /// successfully opened. /// @li \b false if anything goes wrong. /// @@ -207,7 +207,7 @@ class PseudoTerminal /// occur. This can be NULL if no error status is desired. /// /// @return - /// @li \b true when the a master files descriptor is + /// @li \b true when the master files descriptor is /// successfully opened. /// @li \b false if anything goes wrong. /// diff --git a/include/lldb/Utility/SharingPtr.h b/include/lldb/Utility/SharingPtr.h index 1b5f86bbe2df..5c77dad9f7ff 100644 --- a/include/lldb/Utility/SharingPtr.h +++ b/include/lldb/Utility/SharingPtr.h @@ -154,6 +154,7 @@ class SharingPtr void swap(SharingPtr& r); void reset(); template void reset(Y* p); + void reset(std::nullptr_t); element_type* get() const {return ptr_;} element_type& operator*() const {return *ptr_;} @@ -294,6 +295,14 @@ SharingPtr::reset() SharingPtr().swap(*this); } +template +inline +void +SharingPtr::reset (std::nullptr_t p) +{ + reset(); +} + template template inline @@ -547,7 +556,7 @@ class LoggingSharingPtr if (cb_) cb_(baton_, *this, false); } - + void SetCallback(Callback cb, void* baton) { cb_ = cb; diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h index add182c13ecb..9dce69aef32b 100644 --- a/include/lldb/lldb-defines.h +++ b/include/lldb/lldb-defines.h @@ -12,7 +12,7 @@ #include "lldb/lldb-types.h" -#if defined (_WIN32) +#if defined (_MSC_VER) #if defined(EXPORT_LIBLLDB) #define LLDB_API __declspec(dllexport) #elif defined(IMPORT_LIBLLDB) diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index f70ee0cd7b28..28614ffb23e1 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -10,12 +10,34 @@ #ifndef LLDB_lldb_enumerations_h_ #define LLDB_lldb_enumerations_h_ +#ifndef SWIG +// With MSVC, the default type of an enum is always signed, even if one of the +// enumerator values is too large to fit into a signed integer but would +// otherwise fit into an unsigned integer. As a result of this, all of LLDB's +// flag-style enumerations that specify something like eValueFoo = 1u << 31 +// result in negative values. This usually just results in a benign warning, +// but in a few places we actually do comparisons on the enum values, which +// would cause a real bug. Furthermore, there's no way to silence only this +// warning, as it's part of -Wmicrosoft which also catches a whole slew of +// other useful issues. +// +// To make matters worse, early versions of SWIG don't recognize the syntax +// of specifying the underlying type of an enum (and Python doesn't care anyway) +// so we need a way to specify the underlying type when the enum is being used +// from C++ code, but just use a regular enum when swig is pre-processing. +#define FLAGS_ENUM(Name) enum Name : unsigned +#define FLAGS_ANONYMOUS_ENUM() enum : unsigned +#else +#define FLAGS_ENUM(Name) enum Name +#define FLAGS_ANONYMOUS_ENUM() enum +#endif + namespace lldb { //---------------------------------------------------------------------- // Process and Thread States //---------------------------------------------------------------------- - typedef enum StateType + enum StateType { eStateInvalid = 0, eStateUnloaded, ///< Process is object is valid, but not currently loaded @@ -31,12 +53,12 @@ namespace lldb { eStateSuspended ///< Process or thread is in a suspended state as far ///< as the debugger is concerned while other processes ///< or threads get the chance to run. - } StateType; + }; //---------------------------------------------------------------------- // Launch Flags //---------------------------------------------------------------------- - typedef enum LaunchFlags + FLAGS_ENUM(LaunchFlags) { eLaunchFlagNone = 0u, eLaunchFlagExec = (1u << 0), ///< Exec when launching and turn the calling process into a new process @@ -49,46 +71,49 @@ namespace lldb { eLaunchFlagLaunchInSeparateProcessGroup = (1u << 7), ///< Launch the process in a separate process group eLaunchFlagDontSetExitStatus = (1u << 8), ///< If you are going to hand the process off (e.g. to debugserver) ///< set this flag so lldb & the handee don't race to set its exit status. - eLaunchFlagDetachOnError = (1u << 9) ///< If set, then the client stub should detach rather than killing the debugee + eLaunchFlagDetachOnError = (1u << 9), ///< If set, then the client stub should detach rather than killing the debugee ///< if it loses connection with lldb. - } LaunchFlags; + eLaunchFlagShellExpandArguments = (1u << 10), ///< Perform shell-style argument expansion + eLaunchFlagCloseTTYOnExit = (1u << 11), ///< Close the open TTY on exit + }; //---------------------------------------------------------------------- // Thread Run Modes //---------------------------------------------------------------------- - typedef enum RunMode { + enum RunMode + { eOnlyThisThread, eAllThreads, eOnlyDuringStepping - } RunMode; + }; //---------------------------------------------------------------------- // Byte ordering definitions //---------------------------------------------------------------------- - typedef enum ByteOrder + enum ByteOrder { eByteOrderInvalid = 0, eByteOrderBig = 1, eByteOrderPDP = 2, eByteOrderLittle = 4 - } ByteOrder; + }; //---------------------------------------------------------------------- // Register encoding definitions //---------------------------------------------------------------------- - typedef enum Encoding + enum Encoding { eEncodingInvalid = 0, eEncodingUint, // unsigned integer eEncodingSint, // signed integer eEncodingIEEE754, // float eEncodingVector // vector registers - } Encoding; + }; //---------------------------------------------------------------------- // Display format definitions //---------------------------------------------------------------------- - typedef enum Format + enum Format { eFormatDefault = 0, eFormatInvalid = 0, @@ -131,29 +156,29 @@ namespace lldb { eFormatInstruction, // Disassemble an opcode eFormatVoid, // Do not print this kNumFormats - } Format; + }; //---------------------------------------------------------------------- // Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls //---------------------------------------------------------------------- - typedef enum DescriptionLevel + enum DescriptionLevel { eDescriptionLevelBrief = 0, eDescriptionLevelFull, eDescriptionLevelVerbose, eDescriptionLevelInitial, kNumDescriptionLevels - } DescriptionLevel; + }; //---------------------------------------------------------------------- // Script interpreter types //---------------------------------------------------------------------- - typedef enum ScriptLanguage + enum ScriptLanguage { eScriptLanguageNone, eScriptLanguagePython, eScriptLanguageDefault = eScriptLanguagePython - } ScriptLanguage; + }; //---------------------------------------------------------------------- // Register numbering types @@ -161,7 +186,7 @@ namespace lldb { // any of these to the lldb internal register numbering scheme // (eRegisterKindLLDB). //---------------------------------------------------------------------- - typedef enum RegisterKind + enum RegisterKind { eRegisterKindGCC = 0, // the register numbers seen in eh_frame eRegisterKindDWARF, // the register numbers seen DWARF @@ -169,12 +194,12 @@ namespace lldb { eRegisterKindGDB, // the register numbers gdb uses (matches stabs numbers) eRegisterKindLLDB, // lldb's internal register numbers kNumRegisterKinds - } RegisterKind; + }; //---------------------------------------------------------------------- // Thread stop reasons //---------------------------------------------------------------------- - typedef enum StopReason + enum StopReason { eStopReasonInvalid = 0, eStopReasonNone, @@ -187,12 +212,12 @@ namespace lldb { eStopReasonPlanComplete, eStopReasonThreadExiting, eStopReasonInstrumentation - } StopReason; + }; //---------------------------------------------------------------------- // Command Return Status Types //---------------------------------------------------------------------- - typedef enum ReturnStatus + enum ReturnStatus { eReturnStatusInvalid, eReturnStatusSuccessFinishNoResult, @@ -202,13 +227,13 @@ namespace lldb { eReturnStatusStarted, eReturnStatusFailed, eReturnStatusQuit - } ReturnStatus; + }; //---------------------------------------------------------------------- // The results of expression evaluation: //---------------------------------------------------------------------- - typedef enum ExpressionResults + enum ExpressionResults { eExpressionCompleted = 0, eExpressionSetupError, @@ -219,12 +244,12 @@ namespace lldb { eExpressionTimedOut, eExpressionResultUnavailable, eExpressionStoppedForDebug - } ExpressionResults; + }; //---------------------------------------------------------------------- // Connection Status Types //---------------------------------------------------------------------- - typedef enum ConnectionStatus + enum ConnectionStatus { eConnectionStatusSuccess, // Success eConnectionStatusEndOfFile, // End-of-file encountered @@ -233,9 +258,9 @@ namespace lldb { eConnectionStatusNoConnection, // No connection eConnectionStatusLostConnection, // Lost connection while connected to a valid connection eConnectionStatusInterrupted // Interrupted read - } ConnectionStatus; + }; - typedef enum ErrorType + enum ErrorType { eErrorTypeInvalid, eErrorTypeGeneric, ///< Generic errors that can be any value. @@ -243,10 +268,10 @@ namespace lldb { eErrorTypePOSIX, ///< POSIX error codes. eErrorTypeExpression, ///< These are from the ExpressionResults enum. eErrorTypeWin32 ///< Standard Win32 error codes. - } ErrorType; + }; - typedef enum ValueType + enum ValueType { eValueTypeInvalid = 0, eValueTypeVariableGlobal = 1, // globals variable @@ -256,20 +281,20 @@ namespace lldb { eValueTypeRegister = 5, // stack frame register value eValueTypeRegisterSet = 6, // A collection of stack frame register values eValueTypeConstResult = 7 // constant result variables - } ValueType; + }; //---------------------------------------------------------------------- // Token size/granularities for Input Readers //---------------------------------------------------------------------- - typedef enum InputReaderGranularity + enum InputReaderGranularity { eInputReaderGranularityInvalid = 0, eInputReaderGranularityByte, eInputReaderGranularityWord, eInputReaderGranularityLine, eInputReaderGranularityAll - } InputReaderGranularity; + }; //------------------------------------------------------------------ /// These mask bits allow a common interface for queries that can @@ -281,7 +306,7 @@ namespace lldb { /// in this class, and requests that that item be resolved, or /// indicates that the member did get resolved. //------------------------------------------------------------------ - typedef enum SymbolContextItem + FLAGS_ENUM(SymbolContextItem) { eSymbolContextTarget = (1u << 0), ///< Set when \a target is requested from a query, or was located in query results eSymbolContextModule = (1u << 1), ///< Set when \a module is requested from a query, or was located in query results @@ -295,16 +320,16 @@ namespace lldb { ///< eSymbolContextVariable is potentially expensive to lookup so it isn't included in ///< eSymbolContextEverything which stops it from being used during frame PC lookups and ///< many other potential address to symbol context lookups. - } SymbolContextItem; + }; - typedef enum Permissions + FLAGS_ENUM(Permissions) { ePermissionsWritable = (1u << 0), ePermissionsReadable = (1u << 1), ePermissionsExecutable = (1u << 2) - } Permissions; + }; - typedef enum InputReaderAction + enum InputReaderAction { eInputReaderActivate, // reader is newly pushed onto the reader stack eInputReaderAsynchronousOutputWritten, // an async output event occurred; the reader may want to do something @@ -314,9 +339,9 @@ namespace lldb { eInputReaderInterrupt, // reader received an interrupt signal (probably from a control-c) eInputReaderEndOfFile, // reader received an EOF char (probably from a control-d) eInputReaderDone // reader was just popped off the stack and is done - } InputReaderAction; + }; - typedef enum BreakpointEventType + FLAGS_ENUM(BreakpointEventType) { eBreakpointEventTypeInvalidType = (1u << 0), eBreakpointEventTypeAdded = (1u << 1), @@ -330,9 +355,9 @@ namespace lldb { eBreakpointEventTypeConditionChanged = (1u << 9), eBreakpointEventTypeIgnoreChanged = (1u << 10), eBreakpointEventTypeThreadChanged = (1u << 11) - } BreakpointEventType; + }; - typedef enum WatchpointEventType + FLAGS_ENUM(WatchpointEventType) { eWatchpointEventTypeInvalidType = (1u << 0), eWatchpointEventTypeAdded = (1u << 1), @@ -344,7 +369,7 @@ namespace lldb { eWatchpointEventTypeIgnoreChanged = (1u << 10), eWatchpointEventTypeThreadChanged = (1u << 11), eWatchpointEventTypeTypeChanged = (1u << 12) - } WatchpointEventType; + }; //---------------------------------------------------------------------- @@ -355,7 +380,7 @@ namespace lldb { /// The enum -> string code is in LanguageRuntime.cpp, don't change this /// table without updating that code as well. //---------------------------------------------------------------------- - typedef enum LanguageType + enum LanguageType { eLanguageTypeUnknown = 0x0000, ///< Unknown or invalid language value. eLanguageTypeC89 = 0x0001, ///< ISO C:1989. @@ -395,31 +420,39 @@ namespace lldb { eLanguageTypeC_plus_plus_14 = 0x0021, ///< ISO C++:2014. eLanguageTypeFortran03 = 0x0022, ///< ISO Fortran 2003. eLanguageTypeFortran08 = 0x0023, ///< ISO Fortran 2008. + // Vendor Extensions + // Note: LanguageRuntime::GetNameForLanguageType + // assumes these can be used as indexes into array language_names, and + // Language::SetLanguageFromCString and Language::AsCString + // assume these can be used as indexes into array g_languages. + eLanguageTypeMipsAssembler = 0x0024, ///< Mips_Assembler. + eLanguageTypeExtRenderScript = 0x0025, ///< RenderScript. eNumLanguageTypes - } LanguageType; + }; - typedef enum InstrumentationRuntimeType { + enum InstrumentationRuntimeType + { eInstrumentationRuntimeTypeAddressSanitizer = 0x0000, eNumInstrumentationRuntimeTypes - } InstrumentationRuntimeType; + }; - typedef enum DynamicValueType + enum DynamicValueType { eNoDynamicValues = 0, eDynamicCanRunTarget = 1, eDynamicDontRunTarget = 2 - } DynamicValueType; + }; - typedef enum AccessType + enum AccessType { eAccessNone, eAccessPublic, eAccessPrivate, eAccessProtected, eAccessPackage - } AccessType; + }; - typedef enum CommandArgumentType + enum CommandArgumentType { eArgTypeAddress = 0, eArgTypeAddressOrExpression, @@ -493,6 +526,7 @@ namespace lldb { eArgTypeThreadID, eArgTypeThreadIndex, eArgTypeThreadName, + eArgTypeTypeName, eArgTypeUnsignedInteger, eArgTypeUnixSignal, eArgTypeVarName, @@ -504,12 +538,12 @@ namespace lldb { eArgTypeWatchpointIDRange, eArgTypeWatchType, eArgTypeLastArg // Always keep this entry as the last entry in this enumeration!! - } CommandArgumentType; + }; //---------------------------------------------------------------------- // Symbol types //---------------------------------------------------------------------- - typedef enum SymbolType + enum SymbolType { eSymbolTypeAny = 0, eSymbolTypeInvalid = 0, @@ -541,9 +575,9 @@ namespace lldb { eSymbolTypeObjCMetaClass, eSymbolTypeObjCIVar, eSymbolTypeReExported - } SymbolType; + }; - typedef enum SectionType + enum SectionType { eSectionTypeInvalid, eSectionTypeCode, @@ -582,17 +616,16 @@ namespace lldb { eSectionTypeEHFrame, eSectionTypeCompactUnwind, // compact unwind section in Mach-O, __TEXT,__unwind_info eSectionTypeOther - - } SectionType; + }; - typedef enum EmulateInstructionOptions + FLAGS_ENUM(EmulateInstructionOptions) { eEmulateInstructionOptionNone = (0u), eEmulateInstructionOptionAutoAdvancePC = (1u << 0), eEmulateInstructionOptionIgnoreConditions = (1u << 1) - } EmulateInstructionOptions; + }; - typedef enum FunctionNameType + FLAGS_ENUM(FunctionNameType) { eFunctionNameTypeNone = 0u, eFunctionNameTypeAuto = (1u << 1), // Automatically figure out which FunctionNameType @@ -607,13 +640,13 @@ namespace lldb { eFunctionNameTypeMethod = (1u << 4), // Find function by method name (C++) with no namespace or arguments eFunctionNameTypeSelector = (1u << 5), // Find function by selector name (ObjC) names eFunctionNameTypeAny = eFunctionNameTypeAuto // DEPRECATED: use eFunctionNameTypeAuto - } FunctionNameType; + }; //---------------------------------------------------------------------- // Basic types enumeration for the public API SBType::GetBasicType() //---------------------------------------------------------------------- - typedef enum BasicType + enum BasicType { eBasicTypeInvalid = 0, eBasicTypeVoid = 1, @@ -648,9 +681,9 @@ namespace lldb { eBasicTypeObjCSel, eBasicTypeNullPtr, eBasicTypeOther - } BasicType; + }; - typedef enum TypeClass + FLAGS_ENUM(TypeClass) { eTypeClassInvalid = (0u), eTypeClassArray = (1u << 0), @@ -675,9 +708,9 @@ namespace lldb { eTypeClassOther = (1u << 31), // Define a mask that can be used for any type when finding types eTypeClassAny = (0xffffffffu) - } TypeClass; + }; - typedef enum TemplateArgumentKind + enum TemplateArgumentKind { eTemplateArgumentKindNull = 0, eTemplateArgumentKindType, @@ -688,13 +721,13 @@ namespace lldb { eTemplateArgumentKindExpression, eTemplateArgumentKindPack - } TemplateArgumentKind; + }; //---------------------------------------------------------------------- // Options that can be set for a formatter to alter its behavior // Not all of these are applicable to all formatter types //---------------------------------------------------------------------- - typedef enum TypeOptions + FLAGS_ENUM(TypeOptions) { eTypeOptionNone = (0u), eTypeOptionCascade = (1u << 0), @@ -703,8 +736,9 @@ namespace lldb { eTypeOptionHideChildren = (1u << 3), eTypeOptionHideValue = (1u << 4), eTypeOptionShowOneLiner = (1u << 5), - eTypeOptionHideNames = (1u << 6) - } TypeOptions; + eTypeOptionHideNames = (1u << 6), + eTypeOptionNonCacheable = (1u << 7) + }; //---------------------------------------------------------------------- // This is the return value for frame comparisons. If you are comparing frame A to frame B @@ -717,7 +751,7 @@ namespace lldb { // 5) If the two frames are on different threads or processes the comparision is Invalid // 6) If for some reason we can't figure out what went on, we return Unknown. //---------------------------------------------------------------------- - typedef enum FrameComparison + enum FrameComparison { eFrameCompareInvalid, eFrameCompareUnknown, @@ -725,7 +759,7 @@ namespace lldb { eFrameCompareSameParent, eFrameCompareYounger, eFrameCompareOlder - } FrameComparison; + }; //---------------------------------------------------------------------- // Address Class @@ -737,7 +771,7 @@ namespace lldb { // might contain PC relative data and the object file might be able to // tell us that an address in code is data. //---------------------------------------------------------------------- - typedef enum AddressClass + enum AddressClass { eAddressClassInvalid, eAddressClassUnknown, @@ -746,7 +780,7 @@ namespace lldb { eAddressClassData, eAddressClassDebug, eAddressClassRuntime - } AddressClass; + }; //---------------------------------------------------------------------- // File Permissions @@ -755,7 +789,7 @@ namespace lldb { // used with functions that set 'mode_t' to certain values for // permissions. //---------------------------------------------------------------------- - typedef enum FilePermissions + FLAGS_ENUM(FilePermissions) { eFilePermissionsUserRead = (1u << 8), eFilePermissionsUserWrite = (1u << 7), @@ -788,7 +822,7 @@ namespace lldb { eFilePermissionsEveryoneRWX = (eFilePermissionsEveryoneR | eFilePermissionsEveryoneW | eFilePermissionsEveryoneX ), eFilePermissionsFileDefault = eFilePermissionsUserRW, eFilePermissionsDirectoryDefault = eFilePermissionsUserRWX, - } FilePermissions; + }; //---------------------------------------------------------------------- // Queue work item types @@ -796,24 +830,24 @@ namespace lldb { // The different types of work that can be enqueued on a libdispatch // aka Grand Central Dispatch (GCD) queue. //---------------------------------------------------------------------- - typedef enum QueueItemKind + enum QueueItemKind { eQueueItemKindUnknown = 0, eQueueItemKindFunction, eQueueItemKindBlock - } QueueItemKind; + }; //---------------------------------------------------------------------- // Queue type // libdispatch aka Grand Central Dispatch (GCD) queues can be either serial // (executing on one thread) or concurrent (executing on multiple threads). //---------------------------------------------------------------------- - typedef enum QueueKind + enum QueueKind { eQueueKindUnknown = 0, eQueueKindSerial, eQueueKindConcurrent - } QueueKind; + }; //---------------------------------------------------------------------- // Expression Evaluation Stages @@ -821,13 +855,13 @@ namespace lldb { // expression evaluation callback, so that you can interrupt expression // evaluation at the various points in its lifecycle. //---------------------------------------------------------------------- - typedef enum ExpressionEvaluationPhase + enum ExpressionEvaluationPhase { eExpressionEvaluationParse = 0, eExpressionEvaluationIRGen, eExpressionEvaluationExecution, eExpressionEvaluationComplete - } ExpressionEvaluationPhase; + }; //---------------------------------------------------------------------- @@ -835,13 +869,13 @@ namespace lldb { // Indicates what types of events cause the watchpoint to fire. // Used by Native*Protocol-related classes. //---------------------------------------------------------------------- - typedef enum WatchpointKind + FLAGS_ENUM(WatchpointKind) { eWatchpointKindRead = (1u << 0), eWatchpointKindWrite = (1u << 1) - } WatchpointKind; + }; - typedef enum GdbSignal + enum GdbSignal { eGdbSignalBadAccess = 0x91, eGdbSignalBadInstruction = 0x92, @@ -849,52 +883,55 @@ namespace lldb { eGdbSignalEmulation = 0x94, eGdbSignalSoftware = 0x95, eGdbSignalBreakpoint = 0x96 - } GdbRemoteSignal; + }; //---------------------------------------------------------------------- // Used with SBHost::GetPath (lldb::PathType) to find files that are // related to LLDB on the current host machine. Most files are relative // to LLDB or are in known locations. //---------------------------------------------------------------------- - typedef enum PathType + enum PathType { - ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists - ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) - ePathTypeHeaderDir, // Find LLDB header file directory - ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory - ePathTypeLLDBSystemPlugins, // System plug-ins directory - ePathTypeLLDBUserPlugins, // User plug-ins directory - ePathTypeLLDBTempSystemDir, // The LLDB temp directory for this system that will be cleaned up on exit - ePathTypeClangDir // Find path to Clang builtin headers - } PathType; + ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists + ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) + ePathTypeHeaderDir, // Find LLDB header file directory + ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory + ePathTypeLLDBSystemPlugins, // System plug-ins directory + ePathTypeLLDBUserPlugins, // User plug-ins directory + ePathTypeLLDBTempSystemDir, // The LLDB temp directory for this system that will be cleaned up on exit + ePathTypeGlobalLLDBTempSystemDir, // The LLDB temp directory for this system, NOT cleaned up on a process exit. + ePathTypeClangDir // Find path to Clang builtin headers + }; //---------------------------------------------------------------------- // Kind of member function // Used by the type system //---------------------------------------------------------------------- - typedef enum MemberFunctionKind + enum MemberFunctionKind { eMemberFunctionKindUnknown = 0, // Not sure what the type of this is eMemberFunctionKindConstructor, // A function used to create instances eMemberFunctionKindDestructor, // A function used to tear down existing instances eMemberFunctionKindInstanceMethod, // A function that applies to a specific instance eMemberFunctionKindStaticMethod // A function that applies to a type rather than any instance - } MemberFunctionKind; + }; //---------------------------------------------------------------------- // String matching algorithm used by SBTarget //---------------------------------------------------------------------- - typedef enum MatchType { + enum MatchType + { eMatchTypeNormal, eMatchTypeRegex, eMatchTypeStartsWith - } MatchType; + }; //---------------------------------------------------------------------- // Bitmask that describes details about a type //---------------------------------------------------------------------- - typedef enum TypeFlags { + FLAGS_ENUM(TypeFlags) + { eTypeHasChildren = (1u << 0), eTypeHasValue = (1u << 1), eTypeIsArray = (1u << 2), @@ -917,17 +954,100 @@ namespace lldb { eTypeIsFloat = (1u << 19), eTypeIsComplex = (1u << 20), eTypeIsSigned = (1u << 21) - } TypeFlags; + }; + + FLAGS_ENUM(CommandFlags) + { + //---------------------------------------------------------------------- + // eCommandRequiresTarget + // + // Ensures a valid target is contained in m_exe_ctx prior to executing + // the command. If a target doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidTargetDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidTargetDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eCommandRequiresTarget = (1u << 0), + //---------------------------------------------------------------------- + // eCommandRequiresProcess + // + // Ensures a valid process is contained in m_exe_ctx prior to executing + // the command. If a process doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidProcessDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidProcessDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eCommandRequiresProcess = (1u << 1), + //---------------------------------------------------------------------- + // eCommandRequiresThread + // + // Ensures a valid thread is contained in m_exe_ctx prior to executing + // the command. If a thread doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidThreadDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidThreadDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eCommandRequiresThread = (1u << 2), + //---------------------------------------------------------------------- + // eCommandRequiresFrame + // + // Ensures a valid frame is contained in m_exe_ctx prior to executing + // the command. If a frame doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidFrameDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidFrameDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eCommandRequiresFrame = (1u << 3), + //---------------------------------------------------------------------- + // eCommandRequiresRegContext + // + // Ensures a valid register context (from the selected frame if there + // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) + // is available from m_exe_ctx prior to executing the command. If a + // target doesn't exist or is invalid, the command will fail and + // CommandObject::GetInvalidRegContextDescription() will be returned as + // the error. CommandObject subclasses can override the virtual function + // for GetInvalidRegContextDescription() to provide custom strings when + // needed. + //---------------------------------------------------------------------- + eCommandRequiresRegContext = (1u << 4), + //---------------------------------------------------------------------- + // eCommandTryTargetAPILock + // + // Attempts to acquire the target lock if a target is selected in the + // command interpreter. If the command object fails to acquire the API + // lock, the command will fail with an appropriate error message. + //---------------------------------------------------------------------- + eCommandTryTargetAPILock = (1u << 5), + //---------------------------------------------------------------------- + // eCommandProcessMustBeLaunched + // + // Verifies that there is a launched process in m_exe_ctx, if there + // isn't, the command will fail with an appropriate error message. + //---------------------------------------------------------------------- + eCommandProcessMustBeLaunched = (1u << 6), + //---------------------------------------------------------------------- + // eCommandProcessMustBePaused + // + // Verifies that there is a paused process in m_exe_ctx, if there + // isn't, the command will fail with an appropriate error message. + //---------------------------------------------------------------------- + eCommandProcessMustBePaused = (1u << 7) + }; //---------------------------------------------------------------------- // Whether a summary should cap how much data it returns to users or not //---------------------------------------------------------------------- - typedef enum TypeSummaryCapping { + enum TypeSummaryCapping + { eTypeSummaryCapped = true, eTypeSummaryUncapped = false - } TypeSummaryCapping; + }; } // namespace lldb - #endif // LLDB_lldb_enumerations_h_ diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h index 53f59dd62096..e0c2ae4b8b8d 100644 --- a/include/lldb/lldb-forward.h +++ b/include/lldb/lldb-forward.h @@ -58,6 +58,7 @@ class ClangExpressionVariableList; class ClangExpressionVariableList; class ClangExpressionVariables; class ClangFunction; +class ClangModulesDeclVendor; class ClangPersistentVariables; class ClangUserExpression; class ClangUtilityFunction; @@ -82,6 +83,7 @@ class Debugger; class Declaration; class Disassembler; struct DumpValueObjectOptions; +class DynamicCheckerFunctions; class DynamicLoader; class Editline; class EmulateInstruction; @@ -111,8 +113,9 @@ class IOHandler; class IOObject; class IRExecutionUnit; class JITLoader; +class JITLoaderList; class LanguageRuntime; -class SystemRuntime; +class MemoryRegionInfo; class LineTable; class Listener; class Log; @@ -146,6 +149,7 @@ class OptionValueEnumeration; class OptionValueFileSpec; class OptionValueFileSpecList; class OptionValueFormat; +class OptionValueLanguage; class OptionValueFormatEntity; class OptionValuePathMappings; class OptionValueProperties; @@ -167,11 +171,6 @@ class ProcessInstanceInfoMatch; class ProcessLaunchInfo; class Property; struct PropertyDefinition; -class PythonArray; -class PythonDictionary; -class PythonInteger; -class PythonObject; -class PythonString; class RegisterCheckpoint; class RegisterContext; class RegisterLocation; @@ -181,9 +180,7 @@ class RegularExpression; class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; -class ScriptInterpreterObject; #ifndef LLDB_DISABLE_PYTHON -class ScriptInterpreterPython; struct ScriptSummaryFormat; #endif class SearchFilter; @@ -209,6 +206,7 @@ class StreamFile; class StreamString; class StringList; struct StringSummaryFormat; +class SystemRuntime; class TypeSummaryImpl; class TypeSummaryOptions; class Symbol; @@ -231,6 +229,7 @@ class QueueItem; class QueueImpl; class Target; class TargetList; +class TargetProperties; class Thread; class ThreadCollection; class ThreadList; @@ -300,7 +299,13 @@ namespace lldb { typedef std::weak_ptr BreakpointLocationWP; typedef std::shared_ptr BreakpointResolverSP; typedef std::shared_ptr BroadcasterSP; + typedef std::unique_ptr ClangASTContextUP; + typedef std::unique_ptr ClangASTImporterUP; + typedef std::unique_ptr ClangASTSourceUP; typedef std::shared_ptr ClangExpressionVariableSP; + typedef std::unique_ptr ClangModulesDeclVendorUP; + typedef std::unique_ptr ClangPersistentVariablesUP; + typedef std::shared_ptr ClangUserExpressionSP; typedef std::shared_ptr CommandObjectSP; typedef std::shared_ptr CommunicationSP; typedef std::shared_ptr ConnectionSP; @@ -310,7 +315,9 @@ namespace lldb { typedef std::shared_ptr DebuggerSP; typedef std::weak_ptr DebuggerWP; typedef std::shared_ptr DisassemblerSP; + typedef std::unique_ptr DynamicCheckerFunctionsUP; typedef std::shared_ptr DynamicLoaderSP; + typedef std::unique_ptr DynamicLoaderUP; typedef std::shared_ptr EventSP; typedef std::shared_ptr ExecutionContextRefSP; typedef std::shared_ptr FileSP; @@ -322,8 +329,10 @@ namespace lldb { typedef std::shared_ptr IOHandlerSP; typedef std::shared_ptr IOObjectSP; typedef std::shared_ptr JITLoaderSP; + typedef std::unique_ptr JITLoaderListUP; typedef std::shared_ptr LanguageRuntimeSP; typedef std::shared_ptr SystemRuntimeSP; + typedef std::unique_ptr SystemRuntimeUP; typedef std::shared_ptr LineTableSP; typedef std::shared_ptr ListenerSP; typedef std::shared_ptr LogChannelSP; @@ -334,6 +343,7 @@ namespace lldb { typedef std::weak_ptr ObjectFileWP; typedef std::shared_ptr ObjectFileJITDelegateSP; typedef std::weak_ptr ObjectFileJITDelegateWP; + typedef std::unique_ptr OperatingSystemUP; typedef std::shared_ptr OptionValueSP; typedef std::weak_ptr OptionValueWP; typedef std::shared_ptr OptionValueArchSP; @@ -363,15 +373,16 @@ namespace lldb { typedef std::shared_ptr QueueSP; typedef std::weak_ptr QueueWP; typedef std::shared_ptr QueueItemSP; - typedef std::shared_ptr ScriptInterpreterObjectSP; #ifndef LLDB_DISABLE_PYTHON typedef std::shared_ptr ScriptSummaryFormatSP; #endif // #ifndef LLDB_DISABLE_PYTHON typedef std::shared_ptr SectionSP; + typedef std::unique_ptr SectionListUP; typedef std::weak_ptr SectionWP; typedef std::shared_ptr SectionLoadListSP; typedef std::shared_ptr SearchFilterSP; typedef std::shared_ptr SettingsSP; + typedef std::unique_ptr SourceManagerUP; typedef std::shared_ptr StackFrameSP; typedef std::unique_ptr StackFrameUP; typedef std::weak_ptr StackFrameWP; @@ -386,10 +397,12 @@ namespace lldb { typedef std::shared_ptr SymbolFileTypeSP; typedef std::weak_ptr SymbolFileTypeWP; typedef std::shared_ptr SymbolContextSpecifierSP; + typedef std::unique_ptr SymbolVendorUP; typedef std::shared_ptr SyntheticChildrenSP; typedef std::shared_ptr SyntheticChildrenFrontEndSP; typedef std::shared_ptr TargetSP; typedef std::weak_ptr TargetWP; + typedef std::shared_ptr TargetPropertiesSP; typedef std::shared_ptr ThreadSP; typedef std::weak_ptr ThreadWP; typedef std::shared_ptr ThreadCollectionSP; @@ -419,7 +432,7 @@ namespace lldb { typedef std::shared_ptr VariableListSP; typedef std::shared_ptr ValueObjectListSP; typedef std::shared_ptr WatchpointSP; - + } // namespace lldb diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h index f35938ce17b7..7b5c1c9d2c05 100644 --- a/include/lldb/lldb-private-interfaces.h +++ b/include/lldb/lldb-private-interfaces.h @@ -29,6 +29,7 @@ namespace lldb_private typedef EmulateInstruction * (*EmulateInstructionCreateInstance) (const ArchSpec &arch, InstructionType inst_type); typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force); typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language); + typedef lldb::CommandObjectSP (*LanguageRuntimeGetCommandObject) (CommandInterpreter& interpreter); typedef SystemRuntime *(*SystemRuntimeCreateInstance) (Process *process); typedef lldb::PlatformSP (*PlatformCreateInstance) (bool force, const ArchSpec *arch); typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path); diff --git a/include/lldb/lldb-private-types.h b/include/lldb/lldb-private-types.h index cd4867238ef9..cce637fce279 100644 --- a/include/lldb/lldb-private-types.h +++ b/include/lldb/lldb-private-types.h @@ -14,11 +14,22 @@ #include "lldb/lldb-private.h" +namespace llvm +{ +namespace sys +{ +class DynamicLibrary; +} +} + namespace lldb_private { class Platform; class ExecutionContext; + typedef llvm::sys::DynamicLibrary (*LoadPluginCallbackType)(const lldb::DebuggerSP &debugger_sp, + const FileSpec &spec, Error &error); + //---------------------------------------------------------------------- // Every register is described in detail including its name, alternate // name (optional), encoding, size in bytes and the default display diff --git a/include/lldb/lldb-private.h b/include/lldb/lldb-private.h index bbd974303f1f..951b22fc94c5 100644 --- a/include/lldb/lldb-private.h +++ b/include/lldb/lldb-private.h @@ -23,66 +23,13 @@ #include "lldb/lldb-public.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" -#include "lldb/lldb-private-log.h" #include "lldb/lldb-private-types.h" namespace lldb_private { -//------------------------------------------------------------------ -/// Initializes lldb. -/// -/// This function should be called prior to using any lldb -/// classes to ensure they have a chance to do any static -/// initialization that they need to do. -//------------------------------------------------------------------ -void -Initialize(); - - -//------------------------------------------------------------------ -/// Notifies any classes that lldb will be terminating soon. -/// -/// This function will be called when the Debugger shared instance -/// is being destructed and will give classes the ability to clean -/// up any threads or other resources they have that they might not -/// be able to clean up in their own destructors. -/// -/// Internal classes that need this ability will need to add their -/// void T::WillTerminate() method in the body of this function in -/// lldb.cpp to ensure it will get called. -/// -/// TODO: when we start having external plug-ins, we will need a way -/// for plug-ins to register a WillTerminate callback. -//------------------------------------------------------------------ -void -WillTerminate(); - -//------------------------------------------------------------------ -/// Terminates lldb -/// -/// This function optionally can be called when clients are done -/// using lldb functionality to free up any static resources -/// that have been allocated during initialization or during -/// function calls. No lldb functions should be called after -/// calling this function without again calling DCInitialize() -/// again. -//------------------------------------------------------------------ -void -Terminate(); - - const char * GetVersion (); -const char * -GetVoteAsCString (Vote vote); - -const char * -GetSectionTypeAsCString (lldb::SectionType sect_type); - -bool -NameMatches (const char *name, NameMatchType match_type, const char *match); - } // namespace lldb_private diff --git a/source/API/SBAddress.cpp b/source/API/SBAddress.cpp index d6e32b60059b..f95fcb8b3985 100644 --- a/source/API/SBAddress.cpp +++ b/source/API/SBAddress.cpp @@ -14,7 +14,9 @@ #include "lldb/Core/Address.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Core/StreamString.h" #include "lldb/Host/Mutex.h" +#include "lldb/Symbol/LineEntry.h" #include "lldb/Target/Target.h" diff --git a/source/API/SBAttachInfo.cpp b/source/API/SBAttachInfo.cpp new file mode 100644 index 000000000000..07446df27dff --- /dev/null +++ b/source/API/SBAttachInfo.cpp @@ -0,0 +1,242 @@ +//===-- SBAttachInfo.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBAttachInfo.h" + +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBListener.h" +#include "lldb/Target/Process.h" + +using namespace lldb; +using namespace lldb_private; + + +SBAttachInfo::SBAttachInfo () : + m_opaque_sp (new ProcessAttachInfo()) +{ +} + +SBAttachInfo::SBAttachInfo (lldb::pid_t pid) : + m_opaque_sp (new ProcessAttachInfo()) +{ + m_opaque_sp->SetProcessID (pid); +} + +SBAttachInfo::SBAttachInfo (const char *path, bool wait_for) : + m_opaque_sp (new ProcessAttachInfo()) +{ + if (path && path[0]) + m_opaque_sp->GetExecutableFile().SetFile(path, false); + m_opaque_sp->SetWaitForLaunch (wait_for); +} + +SBAttachInfo::SBAttachInfo (const SBAttachInfo &rhs) : + m_opaque_sp (new ProcessAttachInfo()) +{ + *m_opaque_sp = *rhs.m_opaque_sp; +} + +SBAttachInfo::~SBAttachInfo() +{ +} + +lldb_private::ProcessAttachInfo & +SBAttachInfo::ref () +{ + return *m_opaque_sp; +} + +SBAttachInfo & +SBAttachInfo::operator = (const SBAttachInfo &rhs) +{ + if (this != &rhs) + *m_opaque_sp = *rhs.m_opaque_sp; + return *this; +} + +lldb::pid_t +SBAttachInfo::GetProcessID () +{ + return m_opaque_sp->GetProcessID(); +} + +void +SBAttachInfo::SetProcessID (lldb::pid_t pid) +{ + m_opaque_sp->SetProcessID (pid); +} + + +uint32_t +SBAttachInfo::GetResumeCount () +{ + return m_opaque_sp->GetResumeCount(); +} + +void +SBAttachInfo::SetResumeCount (uint32_t c) +{ + m_opaque_sp->SetResumeCount (c); +} + +const char * +SBAttachInfo::GetProcessPluginName () +{ + return m_opaque_sp->GetProcessPluginName(); +} + +void +SBAttachInfo::SetProcessPluginName (const char *plugin_name) +{ + return m_opaque_sp->SetProcessPluginName (plugin_name); +} + +void +SBAttachInfo::SetExecutable (const char *path) +{ + if (path && path[0]) + m_opaque_sp->GetExecutableFile().SetFile(path, false); + else + m_opaque_sp->GetExecutableFile().Clear(); +} + +void +SBAttachInfo::SetExecutable (SBFileSpec exe_file) +{ + if (exe_file.IsValid()) + m_opaque_sp->GetExecutableFile() = exe_file.ref(); + else + m_opaque_sp->GetExecutableFile().Clear(); +} + +bool +SBAttachInfo::GetWaitForLaunch () +{ + return m_opaque_sp->GetWaitForLaunch(); +} + +void +SBAttachInfo::SetWaitForLaunch (bool b) +{ + m_opaque_sp->SetWaitForLaunch (b); +} + +bool +SBAttachInfo::GetIgnoreExisting () +{ + return m_opaque_sp->GetIgnoreExisting(); +} + +void +SBAttachInfo::SetIgnoreExisting (bool b) +{ + m_opaque_sp->SetIgnoreExisting (b); +} + +uint32_t +SBAttachInfo::GetUserID() +{ + return m_opaque_sp->GetUserID(); +} + +uint32_t +SBAttachInfo::GetGroupID() +{ + return m_opaque_sp->GetGroupID(); +} + +bool +SBAttachInfo::UserIDIsValid () +{ + return m_opaque_sp->UserIDIsValid(); +} + +bool +SBAttachInfo::GroupIDIsValid () +{ + return m_opaque_sp->GroupIDIsValid(); +} + +void +SBAttachInfo::SetUserID (uint32_t uid) +{ + m_opaque_sp->SetUserID (uid); +} + +void +SBAttachInfo::SetGroupID (uint32_t gid) +{ + m_opaque_sp->SetGroupID (gid); +} + +uint32_t +SBAttachInfo::GetEffectiveUserID() +{ + return m_opaque_sp->GetEffectiveUserID(); +} + +uint32_t +SBAttachInfo::GetEffectiveGroupID() +{ + return m_opaque_sp->GetEffectiveGroupID(); +} + +bool +SBAttachInfo::EffectiveUserIDIsValid () +{ + return m_opaque_sp->EffectiveUserIDIsValid(); +} + +bool +SBAttachInfo::EffectiveGroupIDIsValid () +{ + return m_opaque_sp->EffectiveGroupIDIsValid (); +} + +void +SBAttachInfo::SetEffectiveUserID (uint32_t uid) +{ + m_opaque_sp->SetEffectiveUserID(uid); +} + +void +SBAttachInfo::SetEffectiveGroupID (uint32_t gid) +{ + m_opaque_sp->SetEffectiveGroupID(gid); +} + +lldb::pid_t +SBAttachInfo::GetParentProcessID () +{ + return m_opaque_sp->GetParentProcessID(); +} + +void +SBAttachInfo::SetParentProcessID (lldb::pid_t pid) +{ + m_opaque_sp->SetParentProcessID (pid); +} + +bool +SBAttachInfo::ParentProcessIDIsValid() +{ + return m_opaque_sp->ParentProcessIDIsValid(); +} + +SBListener +SBAttachInfo::GetListener () +{ + return SBListener(m_opaque_sp->GetListener()); +} + +void +SBAttachInfo::SetListener (SBListener &listener) +{ + m_opaque_sp->SetListener(listener.GetSP()); +} diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp index 193d06e4d920..d901e728105b 100644 --- a/source/API/SBCommandInterpreter.cpp +++ b/source/API/SBCommandInterpreter.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/lldb-types.h" #include "lldb/Core/SourceManager.h" #include "lldb/Core/Listener.h" @@ -20,6 +18,7 @@ #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBEvent.h" #include "lldb/API/SBExecutionContext.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBTarget.h" @@ -446,6 +445,37 @@ SBCommandInterpreter::GetDebugger () return sb_debugger; } +bool +SBCommandInterpreter::GetPromptOnQuit() +{ + if (m_opaque_ptr) + return m_opaque_ptr->GetPromptOnQuit(); + return false; +} + +void +SBCommandInterpreter::SetPromptOnQuit (bool b) +{ + if (m_opaque_ptr) + m_opaque_ptr->SetPromptOnQuit(b); +} + +void +SBCommandInterpreter::ResolveCommand(const char *command_line, SBCommandReturnObject &result) +{ + result.Clear(); + if (command_line && m_opaque_ptr) + { + m_opaque_ptr->ResolveCommand(command_line, result.ref()); + } + else + { + result->AppendError("SBCommandInterpreter or the command line is not valid"); + result->SetStatus(eReturnStatusFailed); + } +} + + CommandInterpreter * SBCommandInterpreter::get () { @@ -532,7 +562,7 @@ SBCommandInterpreter::GetBroadcaster () const char * SBCommandInterpreter::GetBroadcasterClass () { - return Communication::GetStaticBroadcasterClass().AsCString(); + return CommandInterpreter::GetStaticBroadcasterClass().AsCString(); } const char * @@ -547,6 +577,12 @@ SBCommandInterpreter::GetArgumentDescriptionAsCString (const lldb::CommandArgume return CommandObject::GetArgumentDescriptionAsCString (arg_type); } +bool +SBCommandInterpreter::EventIsCommandInterpreterEvent (const lldb::SBEvent &event) +{ + return event.GetBroadcasterClass() == SBCommandInterpreter::GetBroadcasterClass(); +} + bool SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name, lldb::CommandOverrideCallback callback, @@ -566,170 +602,6 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name, return false; } -#ifndef LLDB_DISABLE_PYTHON - -// Defined in the SWIG source file -extern "C" void -init_lldb(void); - -// these are the Pythonic implementations of the required callbacks -// these are scripting-language specific, which is why they belong here -// we still need to use function pointers to them instead of relying -// on linkage-time resolution because the SWIG stuff and this file -// get built at different times -extern "C" bool -LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& sb_frame, - const lldb::BreakpointLocationSP& sb_bp_loc); - -extern "C" bool -LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& sb_frame, - const lldb::WatchpointSP& sb_wp); - -extern "C" bool -LLDBSwigPythonCallTypeScript (const char *python_function_name, - void *session_dictionary, - const lldb::ValueObjectSP& valobj_sp, - void** pyfunct_wrapper, - const lldb::TypeSummaryOptionsSP& options_sp, - std::string& retval); - -extern "C" void* -LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP& valobj_sp); - - -extern "C" void* -LLDBSwigPythonCreateScriptedThreadPlan (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ThreadPlanSP& thread_plan_sp); - -extern "C" bool -LLDBSWIGPythonCallThreadPlan (void *implementor, - const char *method_name, - Event *event_sp, - bool &got_error); - -extern "C" uint32_t -LLDBSwigPython_CalculateNumChildren (void *implementor); - -extern "C" void * -LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); - -extern "C" int -LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); - -extern "C" void * -LLDBSWIGPython_CastPyObjectToSBValue (void* data); - -extern lldb::ValueObjectSP -LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data); - -extern "C" bool -LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); - -extern "C" bool -LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor); - -extern "C" void * -LLDBSwigPython_GetValueSynthProviderInstance (void* implementor); - -extern "C" bool -LLDBSwigPythonCallCommand (const char *python_function_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger, - const char* args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - -extern "C" bool -LLDBSwigPythonCallModuleInit (const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger); - -extern "C" void* -LLDBSWIGPythonCreateOSPlugin (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP& process_sp); - -extern "C" bool -LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name, - const char* session_dictionary_name, - lldb::ProcessSP& process, - std::string& output); - -extern "C" bool -LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name, - const char* session_dictionary_name, - lldb::ThreadSP& thread, - std::string& output); - -extern "C" bool -LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name, - const char* session_dictionary_name, - lldb::TargetSP& target, - std::string& output); - -extern "C" bool -LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name, - const char* session_dictionary_name, - lldb::StackFrameSP& frame, - std::string& output); - -extern "C" bool -LLDBSWIGPythonRunScriptKeywordValue (const char* python_function_name, - const char* session_dictionary_name, - lldb::ValueObjectSP& value, - std::string& output); - -extern "C" void* -LLDBSWIGPython_GetDynamicSetting (void* module, - const char* setting, - const lldb::TargetSP& target_sp); - - -#endif - -void -SBCommandInterpreter::InitializeSWIG () -{ - static bool g_initialized = false; - if (!g_initialized) - { - g_initialized = true; -#ifndef LLDB_DISABLE_PYTHON - ScriptInterpreter::InitializeInterpreter (init_lldb, - LLDBSwigPythonBreakpointCallbackFunction, - LLDBSwigPythonWatchpointCallbackFunction, - LLDBSwigPythonCallTypeScript, - LLDBSwigPythonCreateSyntheticProvider, - LLDBSwigPython_CalculateNumChildren, - LLDBSwigPython_GetChildAtIndex, - LLDBSwigPython_GetIndexOfChildWithName, - LLDBSWIGPython_CastPyObjectToSBValue, - LLDBSWIGPython_GetValueObjectSPFromSBValue, - LLDBSwigPython_UpdateSynthProviderInstance, - LLDBSwigPython_MightHaveChildrenSynthProviderInstance, - LLDBSwigPython_GetValueSynthProviderInstance, - LLDBSwigPythonCallCommand, - LLDBSwigPythonCallModuleInit, - LLDBSWIGPythonCreateOSPlugin, - LLDBSWIGPythonRunScriptKeywordProcess, - LLDBSWIGPythonRunScriptKeywordThread, - LLDBSWIGPythonRunScriptKeywordTarget, - LLDBSWIGPythonRunScriptKeywordFrame, - LLDBSWIGPythonRunScriptKeywordValue, - LLDBSWIGPython_GetDynamicSetting, - LLDBSwigPythonCreateScriptedThreadPlan, - LLDBSWIGPythonCallThreadPlan); -#endif - } -} - lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand (const char* name, const char* help) { @@ -780,6 +652,28 @@ SBCommand::GetHelp () return NULL; } +const char* +SBCommand::GetHelpLong () +{ + if (IsValid ()) + return m_opaque_sp->GetHelpLong (); + return NULL; +} + +void +SBCommand::SetHelp (const char* help) +{ + if (IsValid()) + m_opaque_sp->SetHelp(help); +} + +void +SBCommand::SetHelpLong (const char* help) +{ + if (IsValid()) + m_opaque_sp->SetHelpLong(help); +} + lldb::SBCommand SBCommand::AddMultiwordCommand (const char* name, const char* help) { @@ -809,3 +703,17 @@ SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, c return lldb::SBCommand(); } +uint32_t +SBCommand::GetFlags () +{ + if (!IsValid()) + return 0; + return m_opaque_sp->GetFlags().Get(); +} + +void +SBCommand::SetFlags (uint32_t flags) +{ + if (IsValid()) + m_opaque_sp->GetFlags().Set(flags); +} diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp index a95f2ffc06d9..df2019f5a46b 100644 --- a/source/API/SBDebugger.cpp +++ b/source/API/SBDebugger.cpp @@ -7,12 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBDebugger.h" #include "lldb/lldb-private.h" +#include "lldb/API/SystemInitializerFull.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandInterpreter.h" @@ -33,46 +32,24 @@ #include "lldb/API/SBTypeSummary.h" #include "lldb/API/SBTypeSynthetic.h" - #include "lldb/Core/Debugger.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionGroupPlatform.h" #include "lldb/Target/Process.h" #include "lldb/Target/TargetList.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/DynamicLibrary.h" using namespace lldb; using namespace lldb_private; -SBInputReader::SBInputReader() -{ -} -SBInputReader::~SBInputReader() -{ -} - -SBError -SBInputReader::Initialize(lldb::SBDebugger& sb_debugger, unsigned long (*)(void*, lldb::SBInputReader*, lldb::InputReaderAction, char const*, unsigned long), void*, lldb::InputReaderGranularity, char const*, char const*, bool) -{ - return SBError(); -} - -void -SBInputReader::SetIsDone(bool) -{ -} -bool -SBInputReader::IsActive() const -{ - return false; -} - static llvm::sys::DynamicLibrary LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error) { @@ -107,6 +84,34 @@ LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& er return llvm::sys::DynamicLibrary(); } +static llvm::ManagedStatic g_debugger_lifetime; + +SBInputReader::SBInputReader() +{ +} +SBInputReader::~SBInputReader() +{ +} + +SBError +SBInputReader::Initialize(lldb::SBDebugger &sb_debugger, + unsigned long (*)(void *, lldb::SBInputReader *, lldb::InputReaderAction, char const *, + unsigned long), + void *, lldb::InputReaderGranularity, char const *, char const *, bool) +{ + return SBError(); +} + +void +SBInputReader::SetIsDone(bool) +{ +} +bool +SBInputReader::IsActive() const +{ + return false; +} + void SBDebugger::Initialize () { @@ -115,15 +120,13 @@ SBDebugger::Initialize () if (log) log->Printf ("SBDebugger::Initialize ()"); - SBCommandInterpreter::InitializeSWIG (); - - Debugger::Initialize(LoadPlugin); + g_debugger_lifetime->Initialize(llvm::make_unique(), LoadPlugin); } void SBDebugger::Terminate () { - Debugger::Terminate(); + g_debugger_lifetime->Terminate(); } void diff --git a/source/API/SBEvent.cpp b/source/API/SBEvent.cpp index c62c495b87c8..164636defc9a 100644 --- a/source/API/SBEvent.cpp +++ b/source/API/SBEvent.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBEvent.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBStream.h" diff --git a/source/API/SBExpressionOptions.cpp b/source/API/SBExpressionOptions.cpp index 448ff4cf6dd6..43b7d03064f5 100644 --- a/source/API/SBExpressionOptions.cpp +++ b/source/API/SBExpressionOptions.cpp @@ -185,6 +185,17 @@ SBExpressionOptions::SetSuppressPersistentResult (bool b) return m_opaque_ap->SetResultIsInternal (b); } +const char * +SBExpressionOptions::GetPrefix () const +{ + return m_opaque_ap->GetPrefix(); +} + +void +SBExpressionOptions::SetPrefix (const char *prefix) +{ + return m_opaque_ap->SetPrefix(prefix); +} EvaluateExpressionOptions * SBExpressionOptions::get() const diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp index 8d63fc587d81..dd7435de1b5b 100644 --- a/source/API/SBFileSpec.cpp +++ b/source/API/SBFileSpec.cpp @@ -93,9 +93,8 @@ SBFileSpec::ResolvePath (const char *src_path, char *dst_path, size_t dst_len) { llvm::SmallString<64> result(src_path); lldb_private::FileSpec::Resolve (result); - size_t result_length = std::min(dst_len-1, result.size()); - ::strncpy(dst_path, result.c_str(), result_length + 1); - return result_length; + ::snprintf(dst_path, dst_len, "%s", result.c_str()); + return std::min(dst_len-1, result.size()); } const char * @@ -120,18 +119,19 @@ SBFileSpec::GetFilename() const const char * SBFileSpec::GetDirectory() const { - const char *s = m_opaque_ap->GetDirectory().AsCString(); + FileSpec directory{*m_opaque_ap}; + directory.GetFilename().Clear(); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { - if (s) + if (directory) log->Printf ("SBFileSpec(%p)::GetDirectory () => \"%s\"", - static_cast(m_opaque_ap.get()), s); + static_cast(m_opaque_ap.get()), directory.GetCString()); else log->Printf ("SBFileSpec(%p)::GetDirectory () => NULL", static_cast(m_opaque_ap.get())); } - return s; + return directory.GetCString(); } void diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp index 325f40fd5b56..e845aef41f45 100644 --- a/source/API/SBFrame.cpp +++ b/source/API/SBFrame.cpp @@ -21,6 +21,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Expression/ClangUserExpression.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/Block.h" @@ -44,6 +45,7 @@ #include "lldb/API/SBStream.h" #include "lldb/API/SBSymbolContext.h" #include "lldb/API/SBThread.h" +#include "lldb/API/SBVariablesOptions.h" using namespace lldb; using namespace lldb_private; @@ -452,6 +454,17 @@ SBFrame::GetFrameID () const return frame_idx; } +lldb::addr_t +SBFrame::GetCFA () const +{ + ExecutionContext exe_ctx(m_opaque_sp.get()); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame) + return frame->GetStackID().GetCallFrameAddress(); + return LLDB_INVALID_ADDRESS; +} + + addr_t SBFrame::GetPC () const { @@ -868,32 +881,30 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy case eValueTypeVariableArgument: // function argument variables case eValueTypeVariableLocal: // function local variables { - SymbolContext sc (frame->GetSymbolContext (eSymbolContextBlock)); + SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock)); const bool can_create = true; const bool get_parent_variables = true; const bool stop_if_block_is_inlined_function = true; - if (sc.block && sc.block->AppendVariables (can_create, - get_parent_variables, - stop_if_block_is_inlined_function, - &variable_list)) + if (sc.block) + sc.block->AppendVariables(can_create, + get_parent_variables, + stop_if_block_is_inlined_function, + &variable_list); + if (value_type == eValueTypeVariableGlobal) { - if (value_type == eValueTypeVariableGlobal) - { - const bool get_file_globals = true; - VariableList* frame_vars = frame->GetVariableList(get_file_globals); - if (frame_vars) - frame_vars->AppendVariablesIfUnique(variable_list); - } - ConstString const_name(name); - VariableSP variable_sp(variable_list.FindVariable(const_name,value_type)); - if (variable_sp) - { - value_sp = frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues); - sb_value.SetSP (value_sp, use_dynamic); - break; - } + const bool get_file_globals = true; + VariableList *frame_vars = frame->GetVariableList(get_file_globals); + if (frame_vars) + frame_vars->AppendVariablesIfUnique(variable_list); + } + ConstString const_name(name); + VariableSP variable_sp(variable_list.FindVariable(const_name, value_type)); + if (variable_sp) + { + value_sp = frame->GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues); + sb_value.SetSP(value_sp, use_dynamic); } } break; @@ -1075,17 +1086,43 @@ SBFrame::GetVariables (bool arguments, if (frame && target) { lldb::DynamicValueType use_dynamic = frame->CalculateTarget()->GetPreferDynamicValue(); - value_list = GetVariables (arguments, locals, statics, in_scope_only, use_dynamic); + const bool include_runtime_support_values = target ? target->GetDisplayRuntimeSupportValues() : false; + + SBVariablesOptions options; + options.SetIncludeArguments(arguments); + options.SetIncludeLocals(locals); + options.SetIncludeStatics(statics); + options.SetInScopeOnly(in_scope_only); + options.SetIncludeRuntimeSupportValues(include_runtime_support_values); + options.SetUseDynamic(use_dynamic); + + value_list = GetVariables (options); } return value_list; } -SBValueList +lldb::SBValueList SBFrame::GetVariables (bool arguments, bool locals, bool statics, bool in_scope_only, lldb::DynamicValueType use_dynamic) +{ + ExecutionContext exe_ctx(m_opaque_sp.get()); + Target *target = exe_ctx.GetTargetPtr(); + const bool include_runtime_support_values = target ? target->GetDisplayRuntimeSupportValues() : false; + SBVariablesOptions options; + options.SetIncludeArguments(arguments); + options.SetIncludeLocals(locals); + options.SetIncludeStatics(statics); + options.SetInScopeOnly(in_scope_only); + options.SetIncludeRuntimeSupportValues(include_runtime_support_values); + options.SetUseDynamic(use_dynamic); + return GetVariables(options); +} + +SBValueList +SBFrame::GetVariables (const lldb::SBVariablesOptions& options) { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1096,10 +1133,19 @@ SBFrame::GetVariables (bool arguments, StackFrame *frame = NULL; Target *target = exe_ctx.GetTargetPtr(); + const bool statics = options.GetIncludeStatics(); + const bool arguments = options.GetIncludeArguments(); + const bool locals = options.GetIncludeLocals(); + const bool in_scope_only = options.GetInScopeOnly(); + const bool include_runtime_support_values = options.GetIncludeRuntimeSupportValues(); + const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); + if (log) - log->Printf ("SBFrame::GetVariables (arguments=%i, locals=%i, statics=%i, in_scope_only=%i)", - arguments, locals, statics, in_scope_only); - + log->Printf ("SBFrame::GetVariables (arguments=%i, locals=%i, statics=%i, in_scope_only=%i runtime=%i dynamic=%i)", + arguments, locals, + statics, in_scope_only, + include_runtime_support_values, use_dynamic); + Process *process = exe_ctx.GetProcessPtr(); if (target && process) { @@ -1147,6 +1193,12 @@ SBFrame::GetVariables (bool arguments, continue; ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues)); + + if (false == include_runtime_support_values && + valobj_sp && + true == valobj_sp->IsRuntimeSupportValue()) + continue; + SBValue value_sb; value_sb.SetSP(valobj_sp,use_dynamic); value_list.Append(value_sb); @@ -1448,6 +1500,12 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option bool SBFrame::IsInlined() +{ + return static_cast(this)->IsInlined(); +} + +bool +SBFrame::IsInlined() const { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); ExecutionContext exe_ctx(m_opaque_sp.get()); @@ -1485,6 +1543,12 @@ SBFrame::IsInlined() const char * SBFrame::GetFunctionName() +{ + return static_cast(this)->GetFunctionName(); +} + +const char * +SBFrame::GetFunctionName() const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); const char *name = NULL; @@ -1538,4 +1602,3 @@ SBFrame::GetFunctionName() } return name; } - diff --git a/source/API/SBInstruction.cpp b/source/API/SBInstruction.cpp index 6158418d2f2a..36be94801863 100644 --- a/source/API/SBInstruction.cpp +++ b/source/API/SBInstruction.cpp @@ -180,7 +180,7 @@ SBInstruction::GetDescription (lldb::SBStream &s) // didn't have a stream already created, one will get created... FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format); + m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); return true; } return false; @@ -202,7 +202,7 @@ SBInstruction::Print (FILE *out) StreamFile out_stream (out, false); FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format); + m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); } } diff --git a/source/API/SBInstructionList.cpp b/source/API/SBInstructionList.cpp index 812824b4d2e5..34b0e05079f8 100644 --- a/source/API/SBInstructionList.cpp +++ b/source/API/SBInstructionList.cpp @@ -120,7 +120,7 @@ SBInstructionList::GetDescription (lldb::SBStream &description) module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); } - inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, &format); + inst->Dump (&sref, max_opcode_byte_size, true, false, NULL, &sc, &prev_sc, &format, 0); sref.EOL(); } return true; diff --git a/source/API/SBLanguageRuntime.cpp b/source/API/SBLanguageRuntime.cpp new file mode 100644 index 000000000000..93a54cd76dff --- /dev/null +++ b/source/API/SBLanguageRuntime.cpp @@ -0,0 +1,26 @@ +//===-- SBLanguageRuntime.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBLanguageRuntime.h" +#include "lldb/Target/LanguageRuntime.h" + +using namespace lldb; +using namespace lldb_private; + +lldb::LanguageType +SBLanguageRuntime::GetLanguageTypeFromString (const char *string) +{ + return LanguageRuntime::GetLanguageTypeFromString(string); +} + +const char * +SBLanguageRuntime::GetNameForLanguageType (lldb::LanguageType language) +{ + return LanguageRuntime::GetNameForLanguageType(language); +} diff --git a/source/API/SBLaunchInfo.cpp b/source/API/SBLaunchInfo.cpp index dcb0e1b488ba..54bed8799b8b 100644 --- a/source/API/SBLaunchInfo.cpp +++ b/source/API/SBLaunchInfo.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBLaunchInfo.h" #include "lldb/API/SBFileSpec.h" @@ -36,6 +34,12 @@ SBLaunchInfo::ref () return *m_opaque_sp; } +const lldb_private::ProcessLaunchInfo & +SBLaunchInfo::ref () const +{ + return *m_opaque_sp; +} + lldb::pid_t SBLaunchInfo::GetProcessID() { @@ -169,13 +173,13 @@ SBLaunchInfo::Clear () const char * SBLaunchInfo::GetWorkingDirectory () const { - return m_opaque_sp->GetWorkingDirectory(); + return m_opaque_sp->GetWorkingDirectory().GetCString(); } void SBLaunchInfo::SetWorkingDirectory (const char *working_dir) { - m_opaque_sp->SetWorkingDirectory(working_dir); + m_opaque_sp->SetWorkingDirectory(FileSpec{working_dir, false}); } uint32_t @@ -217,6 +221,18 @@ SBLaunchInfo::SetShell (const char * path) m_opaque_sp->SetShell (FileSpec(path, false)); } +bool +SBLaunchInfo::GetShellExpandArguments () +{ + return m_opaque_sp->GetShellExpandArguments(); +} + +void +SBLaunchInfo::SetShellExpandArguments (bool expand) +{ + m_opaque_sp->SetShellExpandArguments(expand); +} + uint32_t SBLaunchInfo::GetResumeCount () { @@ -244,7 +260,7 @@ SBLaunchInfo::AddDuplicateFileAction (int fd, int dup_fd) bool SBLaunchInfo::AddOpenFileAction (int fd, const char *path, bool read, bool write) { - return m_opaque_sp->AppendOpenFileAction(fd, path, read, write); + return m_opaque_sp->AppendOpenFileAction(fd, FileSpec{path, false}, read, write); } bool diff --git a/source/API/SBListener.cpp b/source/API/SBListener.cpp index 87318739a3a4..643c82d70f78 100644 --- a/source/API/SBListener.cpp +++ b/source/API/SBListener.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBListener.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBDebugger.h" diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp index 0d7dda1aa1f7..0249a7edcd2b 100644 --- a/source/API/SBModule.cpp +++ b/source/API/SBModule.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Symtab.h" @@ -211,34 +212,28 @@ SBModule::GetUUIDString () const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - static char uuid_string_buffer[80]; - const char *uuid_c_string = NULL; - std::string uuid_string; + const char *uuid_cstr = NULL; ModuleSP module_sp (GetSP ()); if (module_sp) - uuid_string = module_sp->GetUUID().GetAsString(); - - if (!uuid_string.empty()) { - strncpy (uuid_string_buffer, uuid_string.c_str(), sizeof (uuid_string_buffer)); - uuid_string_buffer[sizeof (uuid_string_buffer) - 1] = '\0'; - uuid_c_string = uuid_string_buffer; + // We are going to return a "const char *" value through the public + // API, so we need to constify it so it gets added permanently the + // string pool and then we don't need to worry about the lifetime of the + // string as it will never go away once it has been put into the ConstString + // string pool + uuid_cstr = ConstString(module_sp->GetUUID().GetAsString()).GetCString(); + } + + if (uuid_cstr && uuid_cstr[0]) + { + if (log) + log->Printf ("SBModule(%p)::GetUUIDString () => %s", static_cast(module_sp.get()), uuid_cstr); + return uuid_cstr; } if (log) - { - if (!uuid_string.empty()) - { - StreamString s; - module_sp->GetUUID().Dump (&s); - log->Printf ("SBModule(%p)::GetUUIDString () => %s", - static_cast(module_sp.get()), s.GetData()); - } - else - log->Printf ("SBModule(%p)::GetUUIDString () => NULL", - static_cast(module_sp.get())); - } - return uuid_c_string; + log->Printf ("SBModule(%p)::GetUUIDString () => NULL", static_cast(module_sp.get())); + return NULL; } @@ -690,3 +685,30 @@ SBModule::GetVersion (uint32_t *versions, uint32_t num_versions) } } +lldb::SBFileSpec +SBModule::GetSymbolFileSpec() const +{ + lldb::SBFileSpec sb_file_spec; + ModuleSP module_sp(GetSP()); + if (module_sp) + { + SymbolVendor *symbol_vendor_ptr = module_sp->GetSymbolVendor(); + if (symbol_vendor_ptr) + sb_file_spec.SetFileSpec(symbol_vendor_ptr->GetMainFileSpec()); + } + return sb_file_spec; +} + +lldb::SBAddress +SBModule::GetObjectFileHeaderAddress() const +{ + lldb::SBAddress sb_addr; + ModuleSP module_sp (GetSP ()); + if (module_sp) + { + ObjectFile *objfile_ptr = module_sp->GetObjectFile(); + if (objfile_ptr) + sb_addr.ref() = objfile_ptr->GetHeaderAddress(); + } + return sb_addr; +} diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp index b23891d39c21..5662f36b514d 100644 --- a/source/API/SBPlatform.cpp +++ b/source/API/SBPlatform.cpp @@ -329,9 +329,9 @@ SBPlatform::SetWorkingDirectory(const char *path) if (platform_sp) { if (path) - platform_sp->SetWorkingDirectory(ConstString(path)); + platform_sp->SetWorkingDirectory(FileSpec{path, false}); else - platform_sp->SetWorkingDirectory(ConstString()); + platform_sp->SetWorkingDirectory(FileSpec{}); return true; } return false; @@ -378,7 +378,7 @@ SBPlatform::GetTriple() PlatformSP platform_sp(GetSP()); if (platform_sp) { - ArchSpec arch(platform_sp->GetRemoteSystemArchitecture()); + ArchSpec arch(platform_sp->GetSystemArchitecture()); if (arch.IsValid()) { // Const-ify the string so we don't need to worry about the lifetime of the string @@ -545,7 +545,7 @@ SBPlatform::Run (SBPlatformShellCommand &shell_command) shell_command.SetWorkingDirectory(working_dir); } return platform_sp->RunShellCommand(command, - working_dir, + FileSpec{working_dir, false}, &shell_command.m_opaque_ptr->m_status, &shell_command.m_opaque_ptr->m_signo, &shell_command.m_opaque_ptr->m_output, @@ -598,7 +598,7 @@ SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions) PlatformSP platform_sp(GetSP()); if (platform_sp) { - sb_error.ref() = platform_sp->MakeDirectory(path, file_permissions); + sb_error.ref() = platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions); } else { @@ -614,7 +614,7 @@ SBPlatform::GetFilePermissions (const char *path) if (platform_sp) { uint32_t file_permissions = 0; - platform_sp->GetFilePermissions(path, file_permissions); + platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions); return file_permissions; } return 0; @@ -628,7 +628,7 @@ SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions) PlatformSP platform_sp(GetSP()); if (platform_sp) { - sb_error.ref() = platform_sp->SetFilePermissions(path, file_permissions); + sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false}, file_permissions); } else { diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index 9a0b23bc93d2..a1dbf686da03 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBProcess.h" // C Includes @@ -169,11 +167,11 @@ SBProcess::RemoteLaunch (char const **argv, { if (stop_at_entry) launch_flags |= eLaunchFlagStopAtEntry; - ProcessLaunchInfo launch_info (stdin_path, - stdout_path, - stderr_path, - working_directory, - launch_flags); + ProcessLaunchInfo launch_info(FileSpec{stdin_path, false}, + FileSpec{stdout_path, false}, + FileSpec{stderr_path, false}, + FileSpec{working_directory, false}, + launch_flags); Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer(); if (exe_module) launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); @@ -603,6 +601,30 @@ SBProcess::GetStopID(bool include_expression_stops) return 0; } +SBEvent +SBProcess::GetStopEventForStopID(uint32_t stop_id) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBEvent sb_event; + EventSP event_sp; + ProcessSP process_sp(GetSP()); + if (process_sp) + { + Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); + event_sp = process_sp->GetStopEventForStopID(stop_id); + sb_event.reset(event_sp); + } + + if (log) + log->Printf ("SBProcess(%p)::GetStopEventForStopID (stop_id=%" PRIu32 ") => SBEvent(%p)", + static_cast(process_sp.get()), + stop_id, + static_cast(event_sp.get())); + + return sb_event; +} + StateType SBProcess::GetState () { @@ -768,7 +790,7 @@ SBProcess::Destroy () if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); - sb_error.SetError(process_sp->Destroy()); + sb_error.SetError(process_sp->Destroy(false)); } else sb_error.SetErrorString ("SBProcess is invalid"); @@ -821,7 +843,7 @@ SBProcess::Kill () if (process_sp) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); - sb_error.SetError (process_sp->Destroy()); + sb_error.SetError (process_sp->Destroy(true)); } else sb_error.SetErrorString ("SBProcess is invalid"); @@ -918,9 +940,9 @@ SBProcess::GetThreadByID (tid_t tid) ProcessSP process_sp(GetSP()); if (process_sp) { - Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); Process::StopLocker stop_locker; const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); + Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->GetThreadList().FindThreadByID (tid, can_update); sb_thread.SetThread (thread_sp); } @@ -942,9 +964,9 @@ SBProcess::GetThreadByIndexID (uint32_t index_id) ProcessSP process_sp(GetSP()); if (process_sp) { - Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); Process::StopLocker stop_locker; const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); + Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); thread_sp = process_sp->GetThreadList().FindThreadByIndexID (index_id, can_update); sb_thread.SetThread (thread_sp); } @@ -998,10 +1020,16 @@ SBProcess::GetProcessFromEvent (const SBEvent &event) return process; } +bool +SBProcess::GetInterruptedFromEvent (const SBEvent &event) +{ + return Process::ProcessEventData::GetInterruptedFromEvent(event.get()); +} + bool SBProcess::EventIsProcessEvent (const SBEvent &event) { - return strcmp (event.GetBroadcasterClass(), SBProcess::GetBroadcasterClass()) == 0; + return event.GetBroadcasterClass() == SBProcess::GetBroadcasterClass(); } SBBroadcaster diff --git a/source/API/SBQueue.cpp b/source/API/SBQueue.cpp index b19ed72543c2..be4c5fda1540 100644 --- a/source/API/SBQueue.cpp +++ b/source/API/SBQueue.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include #include "lldb/API/SBQueue.h" diff --git a/source/API/SBQueueItem.cpp b/source/API/SBQueueItem.cpp index 6a1aa7bec61a..e7a199b9f0b4 100644 --- a/source/API/SBQueueItem.cpp +++ b/source/API/SBQueueItem.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" #include "lldb/lldb-forward.h" #include "lldb/API/SBAddress.h" diff --git a/source/API/SBSourceManager.cpp b/source/API/SBSourceManager.cpp index 0b8cbfceda0f..8196b91d00b3 100644 --- a/source/API/SBSourceManager.cpp +++ b/source/API/SBSourceManager.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBDebugger.h" #include "lldb/API/SBSourceManager.h" #include "lldb/API/SBTarget.h" diff --git a/source/API/SBSymbol.cpp b/source/API/SBSymbol.cpp index 12a3b317d501..246a455d93a7 100644 --- a/source/API/SBSymbol.cpp +++ b/source/API/SBSymbol.cpp @@ -137,10 +137,11 @@ SBSymbol::GetInstructions (SBTarget target, const char *flavor_string) } if (m_opaque_ptr->ValueIsAddress()) { - ModuleSP module_sp (m_opaque_ptr->GetAddress().GetModule()); + const Address &symbol_addr = m_opaque_ptr->GetAddressRef(); + ModuleSP module_sp = symbol_addr.GetModule(); if (module_sp) { - AddressRange symbol_range (m_opaque_ptr->GetAddress(), m_opaque_ptr->GetByteSize()); + AddressRange symbol_range (symbol_addr, m_opaque_ptr->GetByteSize()); const bool prefer_file_cache = false; sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture (), NULL, @@ -172,7 +173,7 @@ SBSymbol::GetStartAddress () SBAddress addr; if (m_opaque_ptr && m_opaque_ptr->ValueIsAddress()) { - addr.SetAddress (&m_opaque_ptr->GetAddress()); + addr.SetAddress (&m_opaque_ptr->GetAddressRef()); } return addr; } @@ -186,7 +187,7 @@ SBSymbol::GetEndAddress () lldb::addr_t range_size = m_opaque_ptr->GetByteSize(); if (range_size > 0) { - addr.SetAddress (&m_opaque_ptr->GetAddress()); + addr.SetAddress (&m_opaque_ptr->GetAddressRef()); addr->Slide (m_opaque_ptr->GetByteSize()); } } diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index b13d8289560f..923885223a5f 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -7,14 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTarget.h" #include "lldb/lldb-public.h" -#include "lldb/API/SBDebugger.h" #include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBEvent.h" #include "lldb/API/SBExpressionOptions.h" #include "lldb/API/SBFileSpec.h" #include "lldb/API/SBListener.h" @@ -47,12 +46,16 @@ #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/Args.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" - +#include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" @@ -66,230 +69,31 @@ using namespace lldb_private; #define DEFAULT_DISASM_BYTE_SIZE 32 +namespace { -SBAttachInfo::SBAttachInfo () : - m_opaque_sp (new ProcessAttachInfo()) +Error +AttachToProcess (ProcessAttachInfo &attach_info, Target &target) { + Mutex::Locker api_locker (target.GetAPIMutex ()); + + auto process_sp = target.GetProcessSP (); + if (process_sp) + { + const auto state = process_sp->GetState (); + if (process_sp->IsAlive () && state == eStateConnected) + { + // If we are already connected, then we have already specified the + // listener, so if a valid listener is supplied, we need to error out + // to let the client know. + if (attach_info.GetListener ()) + return Error ("process is connected and already has a listener, pass empty listener"); + } + } + + return target.Attach (attach_info, nullptr); } -SBAttachInfo::SBAttachInfo (lldb::pid_t pid) : - m_opaque_sp (new ProcessAttachInfo()) -{ - m_opaque_sp->SetProcessID (pid); -} - -SBAttachInfo::SBAttachInfo (const char *path, bool wait_for) : - m_opaque_sp (new ProcessAttachInfo()) -{ - if (path && path[0]) - m_opaque_sp->GetExecutableFile().SetFile(path, false); - m_opaque_sp->SetWaitForLaunch (wait_for); -} - -SBAttachInfo::SBAttachInfo (const SBAttachInfo &rhs) : - m_opaque_sp (new ProcessAttachInfo()) -{ - *m_opaque_sp = *rhs.m_opaque_sp; -} - -SBAttachInfo::~SBAttachInfo() -{ -} - -lldb_private::ProcessAttachInfo & -SBAttachInfo::ref () -{ - return *m_opaque_sp; -} - -SBAttachInfo & -SBAttachInfo::operator = (const SBAttachInfo &rhs) -{ - if (this != &rhs) - *m_opaque_sp = *rhs.m_opaque_sp; - return *this; -} - -lldb::pid_t -SBAttachInfo::GetProcessID () -{ - return m_opaque_sp->GetProcessID(); -} - -void -SBAttachInfo::SetProcessID (lldb::pid_t pid) -{ - m_opaque_sp->SetProcessID (pid); -} - - -uint32_t -SBAttachInfo::GetResumeCount () -{ - return m_opaque_sp->GetResumeCount(); -} - -void -SBAttachInfo::SetResumeCount (uint32_t c) -{ - m_opaque_sp->SetResumeCount (c); -} - -const char * -SBAttachInfo::GetProcessPluginName () -{ - return m_opaque_sp->GetProcessPluginName(); -} - -void -SBAttachInfo::SetProcessPluginName (const char *plugin_name) -{ - return m_opaque_sp->SetProcessPluginName (plugin_name); -} - -void -SBAttachInfo::SetExecutable (const char *path) -{ - if (path && path[0]) - m_opaque_sp->GetExecutableFile().SetFile(path, false); - else - m_opaque_sp->GetExecutableFile().Clear(); -} - -void -SBAttachInfo::SetExecutable (SBFileSpec exe_file) -{ - if (exe_file.IsValid()) - m_opaque_sp->GetExecutableFile() = exe_file.ref(); - else - m_opaque_sp->GetExecutableFile().Clear(); -} - -bool -SBAttachInfo::GetWaitForLaunch () -{ - return m_opaque_sp->GetWaitForLaunch(); -} - -void -SBAttachInfo::SetWaitForLaunch (bool b) -{ - m_opaque_sp->SetWaitForLaunch (b); -} - -bool -SBAttachInfo::GetIgnoreExisting () -{ - return m_opaque_sp->GetIgnoreExisting(); -} - -void -SBAttachInfo::SetIgnoreExisting (bool b) -{ - m_opaque_sp->SetIgnoreExisting (b); -} - -uint32_t -SBAttachInfo::GetUserID() -{ - return m_opaque_sp->GetUserID(); -} - -uint32_t -SBAttachInfo::GetGroupID() -{ - return m_opaque_sp->GetGroupID(); -} - -bool -SBAttachInfo::UserIDIsValid () -{ - return m_opaque_sp->UserIDIsValid(); -} - -bool -SBAttachInfo::GroupIDIsValid () -{ - return m_opaque_sp->GroupIDIsValid(); -} - -void -SBAttachInfo::SetUserID (uint32_t uid) -{ - m_opaque_sp->SetUserID (uid); -} - -void -SBAttachInfo::SetGroupID (uint32_t gid) -{ - m_opaque_sp->SetGroupID (gid); -} - -uint32_t -SBAttachInfo::GetEffectiveUserID() -{ - return m_opaque_sp->GetEffectiveUserID(); -} - -uint32_t -SBAttachInfo::GetEffectiveGroupID() -{ - return m_opaque_sp->GetEffectiveGroupID(); -} - -bool -SBAttachInfo::EffectiveUserIDIsValid () -{ - return m_opaque_sp->EffectiveUserIDIsValid(); -} - -bool -SBAttachInfo::EffectiveGroupIDIsValid () -{ - return m_opaque_sp->EffectiveGroupIDIsValid (); -} - -void -SBAttachInfo::SetEffectiveUserID (uint32_t uid) -{ - m_opaque_sp->SetEffectiveUserID(uid); -} - -void -SBAttachInfo::SetEffectiveGroupID (uint32_t gid) -{ - m_opaque_sp->SetEffectiveGroupID(gid); -} - -lldb::pid_t -SBAttachInfo::GetParentProcessID () -{ - return m_opaque_sp->GetParentProcessID(); -} - -void -SBAttachInfo::SetParentProcessID (lldb::pid_t pid) -{ - m_opaque_sp->SetParentProcessID (pid); -} - -bool -SBAttachInfo::ParentProcessIDIsValid() -{ - return m_opaque_sp->ParentProcessIDIsValid(); -} - -SBListener -SBAttachInfo::GetListener () -{ - return SBListener(m_opaque_sp->GetListener()); -} - -void -SBAttachInfo::SetListener (SBListener &listener) -{ - m_opaque_sp->SetListener(listener.GetSP()); -} +} // namespace //---------------------------------------------------------------------- // SBTarget constructor @@ -324,6 +128,32 @@ SBTarget::~SBTarget() { } +bool +SBTarget::EventIsTargetEvent (const SBEvent &event) +{ + return Target::TargetEventData::GetEventDataFromEvent(event.get()) != NULL; +} + +SBTarget +SBTarget::GetTargetFromEvent (const SBEvent &event) +{ + return Target::TargetEventData::GetTargetFromEvent (event.get()); +} + +uint32_t +SBTarget::GetNumModulesFromEvent (const SBEvent &event) +{ + const ModuleList module_list = Target::TargetEventData::GetModuleListFromEvent (event.get()); + return module_list.GetSize(); +} + +SBModule +SBTarget::GetModuleAtIndexFromEvent (const uint32_t idx, const SBEvent &event) +{ + const ModuleList module_list = Target::TargetEventData::GetModuleListFromEvent (event.get()); + return SBModule(module_list.GetModuleAtIndex(idx)); +} + const char * SBTarget::GetBroadcasterClassName () { @@ -513,7 +343,11 @@ SBTarget::Launch if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO")) launch_flags |= eLaunchFlagDisableSTDIO; - ProcessLaunchInfo launch_info (stdin_path, stdout_path, stderr_path, working_directory, launch_flags); + ProcessLaunchInfo launch_info(FileSpec{stdin_path, false}, + FileSpec{stdout_path, false}, + FileSpec{stderr_path, false}, + FileSpec{working_directory, false}, + launch_flags); Module *exe_module = target_sp->GetExecutableModulePointer(); if (exe_module) @@ -613,7 +447,6 @@ SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error) Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBProcess sb_process; - ProcessSP process_sp; TargetSP target_sp(GetSP()); if (log) @@ -622,72 +455,34 @@ SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error) if (target_sp) { - Mutex::Locker api_locker (target_sp->GetAPIMutex()); - - StateType state = eStateInvalid; - process_sp = target_sp->GetProcessSP(); - if (process_sp) + ProcessAttachInfo &attach_info = sb_attach_info.ref(); + if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid()) { - state = process_sp->GetState(); - - if (process_sp->IsAlive() && state != eStateConnected) + PlatformSP platform_sp = target_sp->GetPlatform(); + // See if we can pre-verify if a process exists or not + if (platform_sp && platform_sp->IsConnected()) { - if (state == eStateAttaching) - error.SetErrorString ("process attach is in progress"); - else - error.SetErrorString ("a process is already being debugged"); - if (log) - log->Printf ("SBTarget(%p)::Attach (...) => error %s", - static_cast(target_sp.get()), - error.GetCString()); - return sb_process; - } - } - - if (state != eStateConnected) - process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL); - - if (process_sp) - { - ProcessAttachInfo &attach_info = sb_attach_info.ref(); - if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid()) - { - PlatformSP platform_sp = target_sp->GetPlatform(); - // See if we can pre-verify if a process exists or not - if (platform_sp && platform_sp->IsConnected()) + lldb::pid_t attach_pid = attach_info.GetProcessID(); + ProcessInstanceInfo instance_info; + if (platform_sp->GetProcessInfo(attach_pid, instance_info)) { - lldb::pid_t attach_pid = attach_info.GetProcessID(); - ProcessInstanceInfo instance_info; - if (platform_sp->GetProcessInfo(attach_pid, instance_info)) + attach_info.SetUserID(instance_info.GetEffectiveUserID()); + } + else + { + error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid); + if (log) { - attach_info.SetUserID(instance_info.GetEffectiveUserID()); - } - else - { - error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid); - if (log) - { - log->Printf ("SBTarget(%p)::Attach (...) => error %s", - static_cast(target_sp.get()), error.GetCString()); - } - return sb_process; + log->Printf ("SBTarget(%p)::Attach (...) => error %s", + static_cast(target_sp.get()), error.GetCString()); } + return sb_process; } } - error.SetError (process_sp->Attach (attach_info)); - if (error.Success()) - { - sb_process.SetSP (process_sp); - // If we are doing synchronous mode, then wait for the - // process to stop! - if (target_sp->GetDebugger().GetAsyncExecution () == false) - process_sp->WaitForProcessToStop (NULL); - } - } - else - { - error.SetErrorString ("unable to create lldb_private::Process"); } + error.SetError(AttachToProcess(attach_info, *target_sp)); + if (error.Success()) + sb_process.SetSP(target_sp->GetProcessSP()); } else { @@ -697,7 +492,7 @@ SBTarget::Attach (SBAttachInfo &sb_attach_info, SBError& error) if (log) log->Printf ("SBTarget(%p)::Attach (...) => SBProcess(%p)", static_cast(target_sp.get()), - static_cast(process_sp.get())); + static_cast(sb_process.GetSP().get())); return sb_process; } @@ -726,87 +521,37 @@ SBTarget::AttachToProcessWithID Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBProcess sb_process; - ProcessSP process_sp; TargetSP target_sp(GetSP()); if (log) - log->Printf ("SBTarget(%p)::AttachToProcessWithID (listener, pid=%" PRId64 ", error)...", - static_cast(target_sp.get()), pid); + log->Printf ("SBTarget(%p)::%s (listener, pid=%" PRId64 ", error)...", + static_cast(target_sp.get()), + __FUNCTION__, + pid); if (target_sp) { - Mutex::Locker api_locker (target_sp->GetAPIMutex()); + ProcessAttachInfo attach_info; + attach_info.SetProcessID (pid); + if (listener.IsValid()) + attach_info.SetListener(listener.GetSP()); - StateType state = eStateInvalid; - process_sp = target_sp->GetProcessSP(); - if (process_sp) - { - state = process_sp->GetState(); + ProcessInstanceInfo instance_info; + if (target_sp->GetPlatform ()->GetProcessInfo (pid, instance_info)) + attach_info.SetUserID (instance_info.GetEffectiveUserID ()); - if (process_sp->IsAlive() && state != eStateConnected) - { - if (state == eStateAttaching) - error.SetErrorString ("process attach is in progress"); - else - error.SetErrorString ("a process is already being debugged"); - return sb_process; - } - } - - if (state == eStateConnected) - { - // If we are already connected, then we have already specified the - // listener, so if a valid listener is supplied, we need to error out - // to let the client know. - if (listener.IsValid()) - { - error.SetErrorString ("process is connected and already has a listener, pass empty listener"); - return sb_process; - } - } - else - { - if (listener.IsValid()) - process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL); - else - process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL); - } - if (process_sp) - { - sb_process.SetSP (process_sp); - - ProcessAttachInfo attach_info; - attach_info.SetProcessID (pid); - - PlatformSP platform_sp = target_sp->GetPlatform(); - ProcessInstanceInfo instance_info; - if (platform_sp->GetProcessInfo(pid, instance_info)) - { - attach_info.SetUserID(instance_info.GetEffectiveUserID()); - } - error.SetError (process_sp->Attach (attach_info)); - if (error.Success()) - { - // If we are doing synchronous mode, then wait for the - // process to stop! - if (target_sp->GetDebugger().GetAsyncExecution () == false) - process_sp->WaitForProcessToStop (NULL); - } - } - else - { - error.SetErrorString ("unable to create lldb_private::Process"); - } + error.SetError (AttachToProcess (attach_info, *target_sp)); + if (error.Success ()) + sb_process.SetSP (target_sp->GetProcessSP ()); } else - { error.SetErrorString ("SBTarget is invalid"); - } if (log) - log->Printf ("SBTarget(%p)::AttachToProcessWithID (...) => SBProcess(%p)", - static_cast(target_sp.get()), - static_cast(process_sp.get())); + log->Printf ("SBTarget(%p)::%s (...) => SBProcess(%p)", + static_cast(target_sp.get ()), + __FUNCTION__, + static_cast(sb_process.GetSP().get ())); return sb_process; } @@ -822,82 +567,35 @@ SBTarget::AttachToProcessWithName Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBProcess sb_process; - ProcessSP process_sp; TargetSP target_sp(GetSP()); if (log) - log->Printf ("SBTarget(%p)::AttachToProcessWithName (listener, name=%s, wait_for=%s, error)...", - static_cast(target_sp.get()), name, + log->Printf ("SBTarget(%p)::%s (listener, name=%s, wait_for=%s, error)...", + static_cast(target_sp.get()), + __FUNCTION__, + name, wait_for ? "true" : "false"); if (name && target_sp) { - Mutex::Locker api_locker (target_sp->GetAPIMutex()); + ProcessAttachInfo attach_info; + attach_info.GetExecutableFile().SetFile(name, false); + attach_info.SetWaitForLaunch(wait_for); + if (listener.IsValid()) + attach_info.SetListener(listener.GetSP()); - StateType state = eStateInvalid; - process_sp = target_sp->GetProcessSP(); - if (process_sp) - { - state = process_sp->GetState(); - - if (process_sp->IsAlive() && state != eStateConnected) - { - if (state == eStateAttaching) - error.SetErrorString ("process attach is in progress"); - else - error.SetErrorString ("a process is already being debugged"); - return sb_process; - } - } - - if (state == eStateConnected) - { - // If we are already connected, then we have already specified the - // listener, so if a valid listener is supplied, we need to error out - // to let the client know. - if (listener.IsValid()) - { - error.SetErrorString ("process is connected and already has a listener, pass empty listener"); - return sb_process; - } - } - else - { - if (listener.IsValid()) - process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL); - else - process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL); - } - - if (process_sp) - { - sb_process.SetSP (process_sp); - ProcessAttachInfo attach_info; - attach_info.GetExecutableFile().SetFile(name, false); - attach_info.SetWaitForLaunch(wait_for); - error.SetError (process_sp->Attach (attach_info)); - if (error.Success()) - { - // If we are doing synchronous mode, then wait for the - // process to stop! - if (target_sp->GetDebugger().GetAsyncExecution () == false) - process_sp->WaitForProcessToStop (NULL); - } - } - else - { - error.SetErrorString ("unable to create lldb_private::Process"); - } + error.SetError (AttachToProcess (attach_info, *target_sp)); + if (error.Success ()) + sb_process.SetSP (target_sp->GetProcessSP ()); } else - { error.SetErrorString ("SBTarget is invalid"); - } if (log) - log->Printf ("SBTarget(%p)::AttachToPorcessWithName (...) => SBProcess(%p)", + log->Printf ("SBTarget(%p)::%s (...) => SBProcess(%p)", static_cast(target_sp.get()), - static_cast(process_sp.get())); + __FUNCTION__, + static_cast(sb_process.GetSP().get())); return sb_process; } @@ -1112,7 +810,8 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, const LazyBool skip_prologue = eLazyBoolCalculate; const bool internal = false; const bool hardware = false; - *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal, hardware); + const LazyBool move_to_nearest_code = eLazyBoolCalculate; + *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal, hardware, move_to_nearest_code); } if (log) @@ -1359,6 +1058,7 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, RegularExpression regexp(source_regex); FileSpecList source_file_spec_list; const bool hardware = false; + const LazyBool move_to_nearest_code = eLazyBoolCalculate; source_file_spec_list.Append (source_file.ref()); if (module_name && module_name[0]) @@ -1366,11 +1066,11 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false, hardware); + *sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false, hardware, move_to_nearest_code); } else { - *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false, hardware); + *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false, hardware, move_to_nearest_code); } } @@ -1387,9 +1087,9 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, } lldb::SBBreakpoint -SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, - const SBFileSpecList &module_list, - const lldb::SBFileSpecList &source_file_list) +SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, + const SBFileSpecList &module_list, + const lldb::SBFileSpecList &source_file_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1399,8 +1099,9 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, { Mutex::Locker api_locker (target_sp->GetAPIMutex()); const bool hardware = false; + const LazyBool move_to_nearest_code = eLazyBoolCalculate; RegularExpression regexp(source_regex); - *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false, hardware); + *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false, hardware, move_to_nearest_code); } if (log) @@ -2679,3 +2380,20 @@ SBTarget::GetStackRedZoneSize() return 0; } +lldb::SBLaunchInfo +SBTarget::GetLaunchInfo () const +{ + lldb::SBLaunchInfo launch_info(NULL); + TargetSP target_sp(GetSP()); + if (target_sp) + launch_info.ref() = m_opaque_sp->GetProcessLaunchInfo(); + return launch_info; +} + +void +SBTarget::SetLaunchInfo (const lldb::SBLaunchInfo &launch_info) +{ + TargetSP target_sp(GetSP()); + if (target_sp) + m_opaque_sp->SetProcessLaunchInfo(launch_info.ref()); +} diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index 9fe0d029496c..dfc7ce9629f3 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBThread.h" #include "lldb/API/SBSymbolContext.h" @@ -20,13 +18,15 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredData.h" +#include "lldb/Core/ValueObject.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Thread.h" #include "lldb/Target/Process.h" #include "lldb/Target/Queue.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Target/UnixSignals.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlan.h" @@ -114,13 +114,13 @@ SBThread::GetQueue () const else { if (log) - log->Printf ("SBThread(%p)::GetQueueKind() => error: process is running", + log->Printf ("SBThread(%p)::GetQueue() => error: process is running", static_cast(exe_ctx.GetThreadPtr())); } } if (log) - log->Printf ("SBThread(%p)::GetQueueKind () => SBQueue(%p)", + log->Printf ("SBThread(%p)::GetQueue () => SBQueue(%p)", static_cast(exe_ctx.GetThreadPtr()), static_cast(queue_sp.get())); return sb_queue; diff --git a/source/API/SBThreadPlan.cpp b/source/API/SBThreadPlan.cpp index 02b1a8d893b6..2fcd72149409 100644 --- a/source/API/SBThreadPlan.cpp +++ b/source/API/SBThreadPlan.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBThread.h" #include "lldb/API/SBSymbolContext.h" diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp index 66cf46236c65..ee9553ca6abd 100644 --- a/source/API/SBTypeCategory.cpp +++ b/source/API/SBTypeCategory.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTypeCategory.h" #include "lldb/API/SBTypeFilter.h" diff --git a/source/API/SBTypeFilter.cpp b/source/API/SBTypeFilter.cpp index 605e92de6991..8af3e1ff8641 100644 --- a/source/API/SBTypeFilter.cpp +++ b/source/API/SBTypeFilter.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTypeFilter.h" #include "lldb/API/SBStream.h" diff --git a/source/API/SBTypeFormat.cpp b/source/API/SBTypeFormat.cpp index d3ec9bc00bd0..9548fe904cdc 100644 --- a/source/API/SBTypeFormat.cpp +++ b/source/API/SBTypeFormat.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTypeFormat.h" #include "lldb/API/SBStream.h" diff --git a/source/API/SBTypeNameSpecifier.cpp b/source/API/SBTypeNameSpecifier.cpp index 3d03c6a0c539..c58747170b5a 100644 --- a/source/API/SBTypeNameSpecifier.cpp +++ b/source/API/SBTypeNameSpecifier.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTypeNameSpecifier.h" #include "lldb/API/SBStream.h" diff --git a/source/API/SBTypeSummary.cpp b/source/API/SBTypeSummary.cpp index 8a235bf50080..2c114545419c 100644 --- a/source/API/SBTypeSummary.cpp +++ b/source/API/SBTypeSummary.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTypeSummary.h" #include "lldb/API/SBStream.h" diff --git a/source/API/SBTypeSynthetic.cpp b/source/API/SBTypeSynthetic.cpp index 681ed6c032ab..6f9951dc5559 100644 --- a/source/API/SBTypeSynthetic.cpp +++ b/source/API/SBTypeSynthetic.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBTypeSynthetic.h" #include "lldb/API/SBStream.h" diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp index edecb93944ad..ef62c30e42cf 100644 --- a/source/API/SBValue.cpp +++ b/source/API/SBValue.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/API/SBValue.h" #include "lldb/API/SBDeclaration.h" @@ -63,13 +61,19 @@ class ValueImpl lldb::DynamicValueType use_dynamic, bool use_synthetic, const char *name = NULL) : - m_valobj_sp(in_valobj_sp), + m_valobj_sp(), m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic), m_name (name) { - if (!m_name.IsEmpty() && m_valobj_sp) - m_valobj_sp->SetName(m_name); + if (in_valobj_sp) + { + if ( (m_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(lldb::eNoDynamicValues, false)) ) + { + if (!m_name.IsEmpty()) + m_valobj_sp->SetName(m_name); + } + } } ValueImpl (const ValueImpl& rhs) : @@ -152,10 +156,20 @@ class ValueImpl return ValueObjectSP(); } - if (value_sp->GetDynamicValue(m_use_dynamic)) - value_sp = value_sp->GetDynamicValue(m_use_dynamic); - if (value_sp->GetSyntheticValue(m_use_synthetic)) - value_sp = value_sp->GetSyntheticValue(m_use_synthetic); + if (m_use_dynamic != eNoDynamicValues) + { + ValueObjectSP dynamic_sp = value_sp->GetDynamicValue(m_use_dynamic); + if (dynamic_sp) + value_sp = dynamic_sp; + } + + if (m_use_synthetic) + { + ValueObjectSP synthetic_sp = value_sp->GetSyntheticValue(m_use_synthetic); + if (synthetic_sp) + value_sp = synthetic_sp; + } + if (!value_sp) error.SetErrorString("invalid value object"); if (!m_name.IsEmpty()) @@ -969,14 +983,7 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool child_sp = value_sp->GetChildAtIndex (idx, can_create); if (can_create_synthetic && !child_sp) { - if (value_sp->IsPointerType()) - { - child_sp = value_sp->GetSyntheticArrayMemberFromPointer(idx, can_create); - } - else if (value_sp->IsArrayType()) - { - child_sp = value_sp->GetSyntheticArrayMemberFromArray(idx, can_create); - } + child_sp = value_sp->GetSyntheticArrayMember(idx, can_create); } } @@ -1244,6 +1251,22 @@ SBValue::MightHaveChildren () return has_children; } +bool +SBValue::IsRuntimeSupportValue () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + bool is_support = false; + ValueLocker locker; + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (value_sp) + is_support = value_sp->IsRuntimeSupportValue(); + + if (log) + log->Printf ("SBValue(%p)::IsRuntimeSupportValue() => %i", + static_cast(value_sp.get()), is_support); + return is_support; +} + uint32_t SBValue::GetNumChildren () { diff --git a/source/API/SBVariablesOptions.cpp b/source/API/SBVariablesOptions.cpp new file mode 100644 index 000000000000..7c453567c0ae --- /dev/null +++ b/source/API/SBVariablesOptions.cpp @@ -0,0 +1,254 @@ +//===-- SBVariablesOptions.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "lldb/API/SBVariablesOptions.h" + +using namespace lldb; +using namespace lldb_private; + +class VariablesOptionsImpl +{ +public: + VariablesOptionsImpl () : + m_include_arguments(false), + m_include_locals(false), + m_include_statics(false), + m_in_scope_only(false), + m_include_runtime_support_values(false), + m_use_dynamic(lldb::eNoDynamicValues) + {} + + VariablesOptionsImpl (const VariablesOptionsImpl&) = default; + + ~VariablesOptionsImpl () = default; + + VariablesOptionsImpl& + operator = (const VariablesOptionsImpl&) = default; + + bool + GetIncludeArguments () const + { + return m_include_arguments; + } + + void + SetIncludeArguments (bool b) + { + m_include_arguments = b; + } + + bool + GetIncludeLocals () const + { + return m_include_locals; + } + + void + SetIncludeLocals (bool b) + { + m_include_locals = b; + } + + bool + GetIncludeStatics () const + { + return m_include_statics; + } + + void + SetIncludeStatics (bool b) + { + m_include_statics = b; + } + + bool + GetInScopeOnly () const + { + return m_in_scope_only; + } + + void + SetInScopeOnly (bool b) + { + m_in_scope_only = b; + } + + bool + GetIncludeRuntimeSupportValues () const + { + return m_include_runtime_support_values; + } + + void + SetIncludeRuntimeSupportValues (bool b) + { + m_include_runtime_support_values = b; + } + + lldb::DynamicValueType + GetUseDynamic () const + { + return m_use_dynamic; + } + + void + SetUseDynamic (lldb::DynamicValueType d) + { + m_use_dynamic = d; + } + + +private: + bool m_include_arguments : 1; + bool m_include_locals : 1; + bool m_include_statics : 1; + bool m_in_scope_only : 1; + bool m_include_runtime_support_values : 1; + lldb::DynamicValueType m_use_dynamic; +}; + +SBVariablesOptions::SBVariablesOptions () : +m_opaque_ap(new VariablesOptionsImpl()) +{ +} + +SBVariablesOptions::SBVariablesOptions (const SBVariablesOptions& options) : +m_opaque_ap(new VariablesOptionsImpl(options.ref())) +{ +} + +SBVariablesOptions& +SBVariablesOptions::operator = (const SBVariablesOptions& options) +{ + m_opaque_ap.reset(new VariablesOptionsImpl(options.ref())); + return *this; +} + +SBVariablesOptions::~SBVariablesOptions () = default; + +bool +SBVariablesOptions::IsValid () const +{ + return m_opaque_ap.get() != nullptr; +} + +bool +SBVariablesOptions::GetIncludeArguments () const +{ + return m_opaque_ap->GetIncludeArguments(); +} + +void +SBVariablesOptions::SetIncludeArguments (bool arguments) +{ + m_opaque_ap->SetIncludeArguments(arguments); +} + +bool +SBVariablesOptions::GetIncludeLocals () const +{ + return m_opaque_ap->GetIncludeLocals(); +} + +void +SBVariablesOptions::SetIncludeLocals (bool locals) +{ + m_opaque_ap->SetIncludeLocals(locals); +} + +bool +SBVariablesOptions::GetIncludeStatics () const +{ + return m_opaque_ap->GetIncludeStatics(); +} + +void +SBVariablesOptions::SetIncludeStatics (bool statics) +{ + m_opaque_ap->SetIncludeStatics(statics); +} + +bool +SBVariablesOptions::GetInScopeOnly () const +{ + return m_opaque_ap->GetInScopeOnly(); +} + +void +SBVariablesOptions::SetInScopeOnly (bool in_scope_only) +{ + m_opaque_ap->SetInScopeOnly(in_scope_only); +} + +bool +SBVariablesOptions::GetIncludeRuntimeSupportValues () const +{ + return m_opaque_ap->GetIncludeRuntimeSupportValues(); +} + +void +SBVariablesOptions::SetIncludeRuntimeSupportValues (bool runtime_support_values) +{ + m_opaque_ap->SetIncludeRuntimeSupportValues(runtime_support_values); +} + +lldb::DynamicValueType +SBVariablesOptions::GetUseDynamic () const +{ + return m_opaque_ap->GetUseDynamic(); +} + +void +SBVariablesOptions::SetUseDynamic (lldb::DynamicValueType dynamic) +{ + m_opaque_ap->SetUseDynamic(dynamic); +} + +VariablesOptionsImpl * +SBVariablesOptions::operator->() +{ + return m_opaque_ap.operator->(); +} + +const VariablesOptionsImpl * +SBVariablesOptions::operator->() const +{ + return m_opaque_ap.operator->(); +} + +VariablesOptionsImpl * +SBVariablesOptions::get () +{ + return m_opaque_ap.get(); +} + +VariablesOptionsImpl & +SBVariablesOptions::ref() +{ + return *m_opaque_ap; +} + +const VariablesOptionsImpl & +SBVariablesOptions::ref() const +{ + return *m_opaque_ap; +} + +SBVariablesOptions::SBVariablesOptions (VariablesOptionsImpl *lldb_object_ptr) : +m_opaque_ap(std::move(lldb_object_ptr)) +{ +} + +void +SBVariablesOptions::SetOptions (VariablesOptionsImpl *lldb_object_ptr) +{ + m_opaque_ap.reset(std::move(lldb_object_ptr)); +} + diff --git a/source/API/SystemInitializerFull.cpp b/source/API/SystemInitializerFull.cpp new file mode 100644 index 000000000000..731d38a37bee --- /dev/null +++ b/source/API/SystemInitializerFull.cpp @@ -0,0 +1,392 @@ +//===-- SystemInitializerFull.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SystemInitializerFull.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Timer.h" +#include "lldb/Host/Host.h" +#include "lldb/Initialization/SystemInitializerCommon.h" + +#include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h" +#include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" +#include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h" +#include "Plugins/ABI/SysV-arm/ABISysV_arm.h" +#include "Plugins/ABI/SysV-arm64/ABISysV_arm64.h" +#include "Plugins/ABI/SysV-i386/ABISysV_i386.h" +#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" +#include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h" +#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h" +#include "Plugins/ABI/SysV-mips/ABISysV_mips.h" +#include "Plugins/ABI/SysV-mips64/ABISysV_mips64.h" +#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" +#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" +#include "Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h" +#include "Plugins/JITLoader/GDB/JITLoaderGDB.h" +#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h" +#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h" +#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h" +#include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h" +#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h" +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h" +#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" +#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h" +#include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h" +#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h" +#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h" + +#if defined(__APPLE__) +#include "Plugins/Process/mach-core/ProcessMachCore.h" +#include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h" +#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h" +#endif + +#if defined(__FreeBSD__) +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" +#endif + +#if defined(_MSC_VER) +#include "lldb/Host/windows/windows.h" +#include "Plugins/Process/Windows/DynamicLoaderWindows.h" +#include "Plugins/Process/Windows/ProcessWindows.h" +#endif + +#if !defined(LLDB_DISABLE_PYTHON) +#include "lldb/Interpreter/ScriptInterpreterPython.h" +#endif + +#include "llvm/Support/TargetSelect.h" + +#include + +using namespace lldb_private; + +#ifndef LLDB_DISABLE_PYTHON + +// Defined in the SWIG source file +extern "C" void +init_lldb(void); + +// these are the Pythonic implementations of the required callbacks +// these are scripting-language specific, which is why they belong here +// we still need to use function pointers to them instead of relying +// on linkage-time resolution because the SWIG stuff and this file +// get built at different times +extern "C" bool +LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& sb_frame, + const lldb::BreakpointLocationSP& sb_bp_loc); + +extern "C" bool +LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& sb_frame, + const lldb::WatchpointSP& sb_wp); + +extern "C" bool +LLDBSwigPythonCallTypeScript (const char *python_function_name, + void *session_dictionary, + const lldb::ValueObjectSP& valobj_sp, + void** pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP& options_sp, + std::string& retval); + +extern "C" void* +LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp); + +extern "C" void* +LLDBSwigPythonCreateCommandObject (const char *python_class_name, + const char *session_dictionary_name, + const lldb::DebuggerSP debugger_sp); + +extern "C" void* +LLDBSwigPythonCreateScriptedThreadPlan (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ThreadPlanSP& thread_plan_sp); + +extern "C" bool +LLDBSWIGPythonCallThreadPlan (void *implementor, + const char *method_name, + Event *event_sp, + bool &got_error); + +extern "C" size_t +LLDBSwigPython_CalculateNumChildren (void *implementor); + +extern "C" void * +LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); + +extern "C" int +LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); + +extern "C" void * +LLDBSWIGPython_CastPyObjectToSBValue (void* data); + +extern lldb::ValueObjectSP +LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data); + +extern "C" bool +LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); + +extern "C" bool +LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor); + +extern "C" void * +LLDBSwigPython_GetValueSynthProviderInstance (void* implementor); + +extern "C" bool +LLDBSwigPythonCallCommand (const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject &cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); + +extern "C" bool +LLDBSwigPythonCallCommandObject (void *implementor, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject& cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); + +extern "C" bool +LLDBSwigPythonCallModuleInit (const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger); + +extern "C" void* +LLDBSWIGPythonCreateOSPlugin (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP& process_sp); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name, + const char* session_dictionary_name, + lldb::ProcessSP& process, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name, + const char* session_dictionary_name, + lldb::ThreadSP& thread, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name, + const char* session_dictionary_name, + lldb::TargetSP& target, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name, + const char* session_dictionary_name, + lldb::StackFrameSP& frame, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordValue (const char* python_function_name, + const char* session_dictionary_name, + lldb::ValueObjectSP& value, + std::string& output); + +extern "C" void* +LLDBSWIGPython_GetDynamicSetting (void* module, + const char* setting, + const lldb::TargetSP& target_sp); + + +#endif + +SystemInitializerFull::SystemInitializerFull() +{ +} + +SystemInitializerFull::~SystemInitializerFull() +{ +} + +void +SystemInitializerFull::Initialize() +{ + InitializeSWIG(); + + SystemInitializerCommon::Initialize(); + + // Initialize LLVM and Clang + llvm::InitializeAllTargets(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); + + ABIMacOSX_i386::Initialize(); + ABIMacOSX_arm::Initialize(); + ABIMacOSX_arm64::Initialize(); + ABISysV_arm::Initialize(); + ABISysV_arm64::Initialize(); + ABISysV_i386::Initialize(); + ABISysV_x86_64::Initialize(); + ABISysV_ppc::Initialize(); + ABISysV_ppc64::Initialize(); + ABISysV_mips::Initialize(); + ABISysV_mips64::Initialize(); + DisassemblerLLVMC::Initialize(); + + JITLoaderGDB::Initialize(); + ProcessElfCore::Initialize(); + MemoryHistoryASan::Initialize(); + AddressSanitizerRuntime::Initialize(); + + SymbolVendorELF::Initialize(); + SymbolFileDWARF::Initialize(); + SymbolFileSymtab::Initialize(); + UnwindAssemblyInstEmulation::Initialize(); + UnwindAssembly_x86::Initialize(); + EmulateInstructionARM64::Initialize(); + SymbolFileDWARFDebugMap::Initialize(); + ItaniumABILanguageRuntime::Initialize(); + AppleObjCRuntimeV2::Initialize(); + AppleObjCRuntimeV1::Initialize(); + SystemRuntimeMacOSX::Initialize(); + RenderScriptRuntime::Initialize(); + +#if defined(_MSC_VER) + DynamicLoaderWindows::Initialize(); + ProcessWindows::Initialize(); +#endif +#if defined(__FreeBSD__) + ProcessFreeBSD::Initialize(); +#endif +#if defined(__APPLE__) + SymbolVendorMacOSX::Initialize(); + ProcessKDP::Initialize(); + ProcessMachCore::Initialize(); +#endif + //---------------------------------------------------------------------- + // Platform agnostic plugins + //---------------------------------------------------------------------- + platform_gdb_server::PlatformRemoteGDBServer::Initialize(); + + process_gdb_remote::ProcessGDBRemote::Initialize(); + DynamicLoaderStatic::Initialize(); + + // Scan for any system or user LLDB plug-ins + PluginManager::Initialize(); + + // The process settings need to know about installed plug-ins, so the Settings must be initialized + // AFTER PluginManager::Initialize is called. + + Debugger::SettingsInitialize(); +} + +void SystemInitializerFull::InitializeSWIG() +{ +#if !defined(LLDB_DISABLE_PYTHON) + ScriptInterpreterPython::InitializeInterpreter( + init_lldb, + LLDBSwigPythonBreakpointCallbackFunction, + LLDBSwigPythonWatchpointCallbackFunction, + LLDBSwigPythonCallTypeScript, + LLDBSwigPythonCreateSyntheticProvider, + LLDBSwigPythonCreateCommandObject, + LLDBSwigPython_CalculateNumChildren, + LLDBSwigPython_GetChildAtIndex, + LLDBSwigPython_GetIndexOfChildWithName, + LLDBSWIGPython_CastPyObjectToSBValue, + LLDBSWIGPython_GetValueObjectSPFromSBValue, + LLDBSwigPython_UpdateSynthProviderInstance, + LLDBSwigPython_MightHaveChildrenSynthProviderInstance, + LLDBSwigPython_GetValueSynthProviderInstance, + LLDBSwigPythonCallCommand, + LLDBSwigPythonCallCommandObject, + LLDBSwigPythonCallModuleInit, + LLDBSWIGPythonCreateOSPlugin, + LLDBSWIGPythonRunScriptKeywordProcess, + LLDBSWIGPythonRunScriptKeywordThread, + LLDBSWIGPythonRunScriptKeywordTarget, + LLDBSWIGPythonRunScriptKeywordFrame, + LLDBSWIGPythonRunScriptKeywordValue, + LLDBSWIGPython_GetDynamicSetting, + LLDBSwigPythonCreateScriptedThreadPlan, + LLDBSWIGPythonCallThreadPlan); +#endif +} + +void +SystemInitializerFull::Terminate() +{ + Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); + + Debugger::SettingsTerminate(); + + // Terminate and unload and loaded system or user LLDB plug-ins + PluginManager::Terminate(); + ABIMacOSX_i386::Terminate(); + ABIMacOSX_arm::Terminate(); + ABIMacOSX_arm64::Terminate(); + ABISysV_arm::Terminate(); + ABISysV_arm64::Terminate(); + ABISysV_i386::Terminate(); + ABISysV_x86_64::Terminate(); + ABISysV_ppc::Terminate(); + ABISysV_ppc64::Terminate(); + ABISysV_mips::Terminate(); + ABISysV_mips64::Terminate(); + DisassemblerLLVMC::Terminate(); + + JITLoaderGDB::Terminate(); + ProcessElfCore::Terminate(); + MemoryHistoryASan::Terminate(); + AddressSanitizerRuntime::Terminate(); + SymbolVendorELF::Terminate(); + SymbolFileDWARF::Terminate(); + SymbolFileSymtab::Terminate(); + UnwindAssembly_x86::Terminate(); + UnwindAssemblyInstEmulation::Terminate(); + EmulateInstructionARM64::Terminate(); + SymbolFileDWARFDebugMap::Terminate(); + ItaniumABILanguageRuntime::Terminate(); + AppleObjCRuntimeV2::Terminate(); + AppleObjCRuntimeV1::Terminate(); + SystemRuntimeMacOSX::Terminate(); + RenderScriptRuntime::Terminate(); + +#if defined(__APPLE__) + ProcessMachCore::Terminate(); + ProcessKDP::Terminate(); + SymbolVendorMacOSX::Terminate(); +#endif +#if defined(_MSC_VER) + DynamicLoaderWindows::Terminate(); +#endif + +#if defined(__FreeBSD__) + ProcessFreeBSD::Terminate(); +#endif + Debugger::SettingsTerminate(); + + platform_gdb_server::PlatformRemoteGDBServer::Terminate(); + process_gdb_remote::ProcessGDBRemote::Terminate(); + DynamicLoaderStatic::Terminate(); + + // Now shutdown the common parts, in reverse order. + SystemInitializerCommon::Terminate(); +} + +void SystemInitializerFull::TerminateSWIG() +{ + +} diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index beb0f6bc5a6e..23d484f0f68a 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -31,7 +31,6 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/lldb-private-log.h" #include "llvm/Support/Casting.h" using namespace lldb; @@ -877,25 +876,18 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l { s->Printf ("no locations (pending)."); } - else if (num_locations == 1) + else if (num_locations == 1 && show_locations == false) { - // If there is one location only, we'll just print that location information. But don't do this if - // show locations is true, then that will be handled below. - if (show_locations == false) - { - GetLocationAtIndex(0)->GetDescription(s, level); - } - else - { - s->Printf ("%zd locations.", num_locations); - } + // There is only one location, so we'll just print that location information. + GetLocationAtIndex(0)->GetDescription(s, level); } else { - s->Printf ("%zd locations.", num_locations); + s->Printf ("%" PRIu64 " locations.", static_cast(num_locations)); } s->EOL(); break; + case lldb::eDescriptionLevelVerbose: // Verbose mode does a debug dump of the breakpoint Dump (s); @@ -957,6 +949,34 @@ Breakpoint::GetFilterDescription (Stream *s) m_filter_sp->GetDescription (s); } +bool +Breakpoint::EvaluatePrecondition (StoppointCallbackContext &context) +{ + if (!m_precondition_sp) + return true; + + return m_precondition_sp->EvaluatePrecondition(context); +} + +bool +Breakpoint::BreakpointPrecondition::EvaluatePrecondition(StoppointCallbackContext &context) +{ + return true; +} + +void +Breakpoint::BreakpointPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level) +{ +} + +Error +Breakpoint::BreakpointPrecondition::ConfigurePrecondition(Args &options) +{ + Error error; + error.SetErrorString("Base breakpoint precondition has no options."); + return error; +} + void Breakpoint::SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind) { diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index 85233c9374cb..ef9144778df0 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -7,15 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C Includes // C++ Includes #include // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-log.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointID.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" @@ -23,6 +20,8 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/ClangUserExpression.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/Target.h" @@ -535,6 +534,7 @@ bool BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) { m_bp_site_sp = bp_site_sp; + SendBreakpointLocationChangedEvent (eBreakpointEventTypeLocationsResolved); return true; } @@ -590,7 +590,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) s->PutCString ("re-exported target = "); else s->PutCString("where = "); - sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false, true); + sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false, true, true); } else { diff --git a/source/Breakpoint/BreakpointLocationCollection.cpp b/source/Breakpoint/BreakpointLocationCollection.cpp index 5756ccedfaa4..5b6e746f911d 100644 --- a/source/Breakpoint/BreakpointLocationCollection.cpp +++ b/source/Breakpoint/BreakpointLocationCollection.cpp @@ -138,11 +138,17 @@ bool BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context) { bool shouldStop = false; - const size_t count = GetSize(); - for (size_t i = 0; i < count; i++) + size_t i = 0; + size_t prev_size = GetSize(); + while (i < prev_size) { + // ShouldStop can remove the breakpoint from the list if (GetByIndex(i)->ShouldStop(context)) shouldStop = true; + + if (prev_size == GetSize()) + i++; + prev_size = GetSize(); } return shouldStop; } diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp index 33b0ff40e35f..f02eadf86a7c 100644 --- a/source/Breakpoint/BreakpointResolver.cpp +++ b/source/Breakpoint/BreakpointResolver.cpp @@ -25,7 +25,6 @@ #include "lldb/Target/Target.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" -#include "lldb/lldb-private-log.h" using namespace lldb_private; using namespace lldb; diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp index d6647130c54c..193bc413af05 100644 --- a/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/source/Breakpoint/BreakpointResolverAddress.cpp @@ -13,11 +13,11 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-log.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" +#include "lldb/Target/Process.h" #include "lldb/Target/Target.h" using namespace lldb; diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp index 950054c3d720..408998ec83ab 100644 --- a/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/StreamString.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" -#include "lldb/lldb-private-log.h" using namespace lldb; using namespace lldb_private; @@ -33,13 +32,15 @@ BreakpointResolverFileLine::BreakpointResolverFileLine const FileSpec &file_spec, uint32_t line_no, bool check_inlines, - bool skip_prologue + bool skip_prologue, + bool exact_match ) : BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver), m_file_spec (file_spec), m_line_number (line_no), m_inlines (check_inlines), - m_skip_prologue(skip_prologue) + m_skip_prologue(skip_prologue), + m_exact_match(exact_match) { } @@ -79,7 +80,7 @@ BreakpointResolverFileLine::SearchCallback if (cu_sp) { if (filter.CompUnitPasses(*cu_sp)) - cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list); + cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, m_exact_match, eSymbolContextEverything, sc_list); } } StreamString s; @@ -101,7 +102,7 @@ BreakpointResolverFileLine::GetDepth() void BreakpointResolverFileLine::GetDescription (Stream *s) { - s->Printf ("file = '%s', line = %u", m_file_spec.GetPath().c_str(), m_line_number); + s->Printf ("file = '%s', line = %u, exact_match = %d", m_file_spec.GetPath().c_str(), m_line_number, m_exact_match); } void @@ -117,7 +118,8 @@ BreakpointResolverFileLine::CopyForBreakpoint (Breakpoint &breakpoint) m_file_spec, m_line_number, m_inlines, - m_skip_prologue)); + m_skip_prologue, + m_exact_match)); return ret_sp; } diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp index c71d9bf5ba8c..e7bce0524c57 100644 --- a/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/StreamString.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Target/Target.h" -#include "lldb/lldb-private-log.h" using namespace lldb; using namespace lldb_private; @@ -30,10 +29,12 @@ using namespace lldb_private; BreakpointResolverFileRegex::BreakpointResolverFileRegex ( Breakpoint *bkpt, - RegularExpression ®ex + RegularExpression ®ex, + bool exact_match ) : BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver), - m_regex (regex) + m_regex (regex), + m_exact_match (exact_match) { } @@ -65,9 +66,8 @@ BreakpointResolverFileRegex::SearchCallback { SymbolContextList sc_list; const bool search_inlines = false; - const bool exact = false; - cu->ResolveSymbolContext (cu_file_spec, line_matches[i], search_inlines, exact, eSymbolContextEverything, sc_list); + cu->ResolveSymbolContext (cu_file_spec, line_matches[i], search_inlines, m_exact_match, eSymbolContextEverything, sc_list); const bool skip_prologue = true; BreakpointResolver::SetSCMatchesByLine (filter, sc_list, skip_prologue, m_regex.GetText()); @@ -86,7 +86,7 @@ BreakpointResolverFileRegex::GetDepth() void BreakpointResolverFileRegex::GetDescription (Stream *s) { - s->Printf ("source regex = \"%s\"", m_regex.GetText()); + s->Printf ("source regex = \"%s\", exact_match = %d", m_regex.GetText(), m_exact_match); } void @@ -98,7 +98,7 @@ BreakpointResolverFileRegex::Dump (Stream *s) const lldb::BreakpointResolverSP BreakpointResolverFileRegex::CopyForBreakpoint (Breakpoint &breakpoint) { - lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileRegex(&breakpoint, m_regex)); + lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileRegex(&breakpoint, m_regex, m_exact_match)); return ret_sp; } diff --git a/source/Breakpoint/BreakpointSite.cpp b/source/Breakpoint/BreakpointSite.cpp index 469514b03f8a..e9ce812e7732 100644 --- a/source/Breakpoint/BreakpointSite.cpp +++ b/source/Breakpoint/BreakpointSite.cpp @@ -11,11 +11,14 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSiteList.h" +#include "lldb/Core/Stream.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index c65dd9d460f4..37696e3bbfdb 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C Includes #include #if defined(__APPLE__) || defined(__linux__) @@ -25,6 +23,7 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/Target.h" diff --git a/source/Commands/CommandObjectApropos.cpp b/source/Commands/CommandObjectApropos.cpp index 02dc7269775d..47890b1e83b7 100644 --- a/source/Commands/CommandObjectApropos.cpp +++ b/source/Commands/CommandObjectApropos.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectApropos.h" // C Includes @@ -17,6 +15,7 @@ // Project includes #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/Property.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" diff --git a/source/Commands/CommandObjectArgs.cpp b/source/Commands/CommandObjectArgs.cpp index b0fe42bc2446..cf32d104911c 100644 --- a/source/Commands/CommandObjectArgs.cpp +++ b/source/Commands/CommandObjectArgs.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectArgs.h" // C Includes @@ -25,8 +23,10 @@ #include "lldb/Host/Host.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Variable.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index 025524b3b9a5..4cbcb70d5fd2 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectBreakpoint.h" #include "CommandObjectBreakpointCommand.h" @@ -21,12 +19,14 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamString.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Target/StackFrame.h" @@ -110,9 +110,11 @@ class CommandObjectBreakpointSet : public CommandObjectParsed m_catch_bp (false), m_throw_bp (true), m_hardware (false), - m_language (eLanguageTypeUnknown), + m_exception_language (eLanguageTypeUnknown), m_skip_prologue (eLazyBoolCalculate), - m_one_shot (false) + m_one_shot (false), + m_all_files (false), + m_move_to_nearest_code (eLazyBoolCalculate) { } @@ -135,15 +137,23 @@ class CommandObjectBreakpointSet : public CommandObjectParsed } break; + case 'A': + m_all_files = true; + break; + case 'b': m_func_names.push_back (option_arg); m_func_name_type_mask |= eFunctionNameTypeBase; break; case 'C': - m_column = StringConvert::ToUInt32 (option_arg, 0); + { + bool success; + m_column = StringConvert::ToUInt32 (option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid column number: %s", option_arg); break; - + } case 'c': m_condition.assign(option_arg); break; @@ -162,16 +172,16 @@ class CommandObjectBreakpointSet : public CommandObjectParsed case eLanguageTypeC: case eLanguageTypeC99: case eLanguageTypeC11: - m_language = eLanguageTypeC; + m_exception_language = eLanguageTypeC; break; case eLanguageTypeC_plus_plus: case eLanguageTypeC_plus_plus_03: case eLanguageTypeC_plus_plus_11: case eLanguageTypeC_plus_plus_14: - m_language = eLanguageTypeC_plus_plus; + m_exception_language = eLanguageTypeC_plus_plus; break; case eLanguageTypeObjC: - m_language = eLanguageTypeObjC; + m_exception_language = eLanguageTypeObjC; break; case eLanguageTypeObjC_plus_plus: error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c"); @@ -231,8 +241,28 @@ class CommandObjectBreakpointSet : public CommandObjectParsed break; case 'l': - m_line_num = StringConvert::ToUInt32 (option_arg, 0); + { + bool success; + m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat ("invalid line number: %s.", option_arg); break; + } + + case 'm': + { + bool success; + bool value; + value = Args::StringToBoolean (option_arg, true, &success); + if (value) + m_move_to_nearest_code = eLazyBoolYes; + else + m_move_to_nearest_code = eLazyBoolNo; + + if (!success) + error.SetErrorStringWithFormat ("Invalid boolean value for move-to-nearest-code option: '%s'", option_arg); + break; + } case 'M': m_func_names.push_back (option_arg); @@ -253,6 +283,11 @@ class CommandObjectBreakpointSet : public CommandObjectParsed m_one_shot = true; break; + case 'O': + m_exception_extra_args.AppendArgument ("-O"); + m_exception_extra_args.AppendArgument (option_arg); + break; + case 'p': m_source_text_regexp.assign (option_arg); break; @@ -334,11 +369,14 @@ class CommandObjectBreakpointSet : public CommandObjectParsed m_catch_bp = false; m_throw_bp = true; m_hardware = false; - m_language = eLanguageTypeUnknown; + m_exception_language = eLanguageTypeUnknown; m_skip_prologue = eLazyBoolCalculate; m_one_shot = false; m_use_dummy = false; m_breakpoint_names.clear(); + m_all_files = false; + m_exception_extra_args.Clear(); + m_move_to_nearest_code = eLazyBoolCalculate; } const OptionDefinition* @@ -372,10 +410,13 @@ class CommandObjectBreakpointSet : public CommandObjectParsed bool m_catch_bp; bool m_throw_bp; bool m_hardware; // Request to use hardware breakpoints - lldb::LanguageType m_language; + lldb::LanguageType m_exception_language; LazyBool m_skip_prologue; bool m_one_shot; bool m_use_dummy; + bool m_all_files; + Args m_exception_extra_args; + LazyBool m_move_to_nearest_code; }; @@ -413,7 +454,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed break_type = eSetTypeFunctionRegexp; else if (!m_options.m_source_text_regexp.empty()) break_type = eSetTypeSourceRegexp; - else if (m_options.m_language != eLanguageTypeUnknown) + else if (m_options.m_exception_language != eLanguageTypeUnknown) break_type = eSetTypeException; Breakpoint *bp = NULL; @@ -453,7 +494,8 @@ class CommandObjectBreakpointSet : public CommandObjectParsed check_inlines, m_options.m_skip_prologue, internal, - m_options.m_hardware).get(); + m_options.m_hardware, + m_options.m_move_to_nearest_code).get(); } break; @@ -505,7 +547,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed { const size_t num_files = m_options.m_filenames.GetSize(); - if (num_files == 0) + if (num_files == 0 && !m_options.m_all_files) { FileSpec file; if (!GetDefaultFile (target, file, result)) @@ -534,15 +576,27 @@ class CommandObjectBreakpointSet : public CommandObjectParsed &(m_options.m_filenames), regexp, internal, - m_options.m_hardware).get(); + m_options.m_hardware, + m_options.m_move_to_nearest_code).get(); } break; case eSetTypeException: { - bp = target->CreateExceptionBreakpoint (m_options.m_language, + Error precond_error; + bp = target->CreateExceptionBreakpoint (m_options.m_exception_language, m_options.m_catch_bp, m_options.m_throw_bp, - m_options.m_hardware).get(); + internal, + &m_options.m_exception_extra_args, + &precond_error).get(); + if (precond_error.Fail()) + { + result.AppendErrorWithFormat("Error setting extra exception arguments: %s", + precond_error.AsCString()); + target->RemoveBreakpointByID(bp->GetID()); + result.SetStatus(eReturnStatusFailed); + return false; + } } break; default: @@ -654,6 +708,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed #define LLDB_OPT_FILE ( LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2 ) #define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 ) #define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) ) +#define LLDB_OPT_MOVE_TO_NEAREST_CODE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_9 ) OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = @@ -729,6 +784,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = "specified with the -f option. The -f option can be specified more than once. " "If no source files are specified, uses the current \"default source file\"" }, + { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "All files are searched for source pattern matches." }, + { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" }, @@ -738,6 +796,10 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, +// Don't add this option till it actually does something useful... +// { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeTypeName, +// "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, + { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." }, @@ -747,6 +809,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakopint."}, + { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, + "Move breakpoints to nearest code. If not set the target.move-to-nearest-code setting is used." }, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1940,15 +2005,15 @@ class BreakpointNameOptionGroup : public OptionGroup { case 'N': if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success()) - m_name.SetValueFromCString(option_value); + m_name.SetValueFromString(option_value); break; case 'B': - if (m_breakpoint.SetValueFromCString(option_value).Fail()) + if (m_breakpoint.SetValueFromString(option_value).Fail()) error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value); break; case 'D': - if (m_use_dummy.SetValueFromCString(option_value).Fail()) + if (m_use_dummy.SetValueFromString(option_value).Fail()) error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value); break; @@ -2187,7 +2252,6 @@ class CommandObjectBreakpointNameList : public CommandObjectParsed return &m_option_group; } -protected: protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index 8f8404b712a5..180ab600a50e 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C Includes // C++ Includes diff --git a/source/Commands/CommandObjectBugreport.cpp b/source/Commands/CommandObjectBugreport.cpp new file mode 100644 index 000000000000..f171d2f6267f --- /dev/null +++ b/source/Commands/CommandObjectBugreport.cpp @@ -0,0 +1,145 @@ +//===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectBugreport.h" + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes + +// Project includes +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionGroupOutputFile.h" +#include "lldb/Target/Thread.h" + +using namespace lldb; +using namespace lldb_private; + +//------------------------------------------------------------------------- +// "bugreport unwind" +//------------------------------------------------------------------------- + +class CommandObjectBugreportUnwind : public CommandObjectParsed +{ +public: + CommandObjectBugreportUnwind(CommandInterpreter &interpreter) : + CommandObjectParsed(interpreter, + "bugreport unwind", + "Create a bugreport for a bug in the stack unwinding code.", + nullptr), + m_option_group(interpreter), + m_outfile_options() + { + m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); + m_option_group.Finalize(); + } + + ~CommandObjectBugreportUnwind() + { + } + + Options * + GetOptions() override + { + return &m_option_group; + } + +protected: + bool + DoExecute(Args& command, CommandReturnObject &result) override + { + StringList commands; + commands.AppendString("thread backtrace"); + + Thread *thread = m_exe_ctx.GetThreadPtr(); + if (thread) + { + char command_buffer[256]; + + uint32_t frame_count = thread->GetStackFrameCount(); + for (uint32_t i = 0; i < frame_count; ++i) + { + StackFrameSP frame = thread->GetStackFrameAtIndex(i); + lldb::addr_t pc = frame->GetStackID().GetPC(); + + snprintf(command_buffer, sizeof(command_buffer), "disassemble --bytes --address 0x%" PRIx64, pc); + commands.AppendString(command_buffer); + + snprintf(command_buffer, sizeof(command_buffer), "image show-unwind --address 0x%" PRIx64, pc); + commands.AppendString(command_buffer); + } + } + + const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); + if (outfile_spec) + { + char path[PATH_MAX]; + outfile_spec.GetPath (path, sizeof(path)); + + uint32_t open_options = File::eOpenOptionWrite | + File::eOpenOptionCanCreate | + File::eOpenOptionAppend | + File::eOpenOptionCloseOnExec; + + const bool append = m_outfile_options.GetAppend().GetCurrentValue(); + if (!append) + open_options |= File::eOpenOptionTruncate; + + StreamFileSP outfile_stream = std::make_shared(); + Error error = outfile_stream->GetFile().Open(path, open_options); + if (error.Fail()) + { + result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", + path, + append ? "append" : "write", + error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + result.SetImmediateOutputStream(outfile_stream); + } + + CommandInterpreterRunOptions options; + options.SetStopOnError(false); + options.SetEchoCommands(true); + options.SetPrintResults(true); + options.SetAddToHistory(false); + m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); + + return result.Succeeded(); + } + +private: + OptionGroupOptions m_option_group; + OptionGroupOutputFile m_outfile_options; +}; + +#pragma mark CommandObjectMultiwordBugreport + +//------------------------------------------------------------------------- +// CommandObjectMultiwordBugreport +//------------------------------------------------------------------------- + +CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport(CommandInterpreter &interpreter) : + CommandObjectMultiword(interpreter, + "bugreport", + "Set of commands for creating domain specific bugreports.", + "bugreport []") +{ + + LoadSubCommand("unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); +} + +CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport () +{ +} diff --git a/source/Commands/CommandObjectBugreport.h b/source/Commands/CommandObjectBugreport.h new file mode 100644 index 000000000000..d062e0d79373 --- /dev/null +++ b/source/Commands/CommandObjectBugreport.h @@ -0,0 +1,36 @@ +//===-- CommandObjectBugreport.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CommandObjectBugreport_h_ +#define liblldb_CommandObjectBugreport_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/CommandObjectMultiword.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// CommandObjectMultiwordBugreport +//------------------------------------------------------------------------- + +class CommandObjectMultiwordBugreport : public CommandObjectMultiword +{ +public: + CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); + + virtual + ~CommandObjectMultiwordBugreport(); +}; + +} // namespace lldb_private + +#endif // liblldb_CommandObjectBugreport_h_ diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index f98eac055f24..5fd99cfdabf4 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectCommands.h" // C Includes @@ -29,7 +27,6 @@ #include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" using namespace lldb; using namespace lldb_private; @@ -85,7 +82,7 @@ class CommandObjectCommandsHistory : public CommandObjectParsed switch (short_option) { case 'c': - error = m_count.SetValueFromCString(option_arg,eVarSetOperationAssign); + error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign); break; case 's': if (option_arg && strcmp("end", option_arg) == 0) @@ -94,10 +91,10 @@ class CommandObjectCommandsHistory : public CommandObjectParsed m_start_idx.SetOptionWasSet(); } else - error = m_start_idx.SetValueFromCString(option_arg,eVarSetOperationAssign); + error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign); break; case 'e': - error = m_stop_idx.SetValueFromCString(option_arg,eVarSetOperationAssign); + error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign); break; case 'C': m_clear.SetCurrentValue(true); @@ -326,15 +323,15 @@ class CommandObjectCommandsSource : public CommandObjectParsed switch (short_option) { case 'e': - error = m_stop_on_error.SetValueFromCString(option_arg); + error = m_stop_on_error.SetValueFromString(option_arg); break; case 'c': - error = m_stop_on_continue.SetValueFromCString(option_arg); + error = m_stop_on_continue.SetValueFromString(option_arg); break; case 's': - error = m_silent_run.SetValueFromCString(option_arg); + error = m_silent_run.SetValueFromString(option_arg); break; default: @@ -1430,6 +1427,130 @@ class CommandObjectPythonFunction : public CommandObjectRaw }; +class CommandObjectScriptingObject : public CommandObjectRaw +{ +private: + StructuredData::GenericSP m_cmd_obj_sp; + ScriptedCommandSynchronicity m_synchro; + bool m_fetched_help_short:1; + bool m_fetched_help_long:1; + +public: + + CommandObjectScriptingObject (CommandInterpreter &interpreter, + std::string name, + StructuredData::GenericSP cmd_obj_sp, + ScriptedCommandSynchronicity synch) : + CommandObjectRaw (interpreter, + name.c_str(), + NULL, + NULL), + m_cmd_obj_sp(cmd_obj_sp), + m_synchro(synch), + m_fetched_help_short(false), + m_fetched_help_long(false) + { + StreamString stream; + stream.Printf("For more information run 'help %s'",name.c_str()); + SetHelp(stream.GetData()); + if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter()) + GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); + } + + virtual + ~CommandObjectScriptingObject () + { + } + + virtual bool + IsRemovable () const + { + return true; + } + + StructuredData::GenericSP + GetImplementingObject () + { + return m_cmd_obj_sp; + } + + ScriptedCommandSynchronicity + GetSynchronicity () + { + return m_synchro; + } + + virtual const char * + GetHelp () + { + if (!m_fetched_help_short) + { + ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) + { + std::string docstring; + m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring); + if (!docstring.empty()) + SetHelp(docstring); + } + } + return CommandObjectRaw::GetHelp(); + } + + virtual const char * + GetHelpLong () + { + if (!m_fetched_help_long) + { + ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); + if (scripter) + { + std::string docstring; + m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring); + if (!docstring.empty()) + SetHelpLong(docstring); + } + } + return CommandObjectRaw::GetHelpLong(); + } + +protected: + virtual bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) + { + ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); + + Error error; + + result.SetStatus(eReturnStatusInvalid); + + if (!scripter || scripter->RunScriptBasedCommand(m_cmd_obj_sp, + raw_command_line, + m_synchro, + result, + error, + m_exe_ctx) == false) + { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + else + { + // Don't change the status if the command already set it... + if (result.GetStatus() == eReturnStatusInvalid) + { + if (result.GetOutputData() == NULL || result.GetOutputData()[0] == '\0') + result.SetStatus(eReturnStatusSuccessFinishNoResult); + else + result.SetStatus(eReturnStatusSuccessFinishResult); + } + } + + return result.Succeeded(); + } + +}; + //------------------------------------------------------------------------- // CommandObjectCommandsScriptImport //------------------------------------------------------------------------- @@ -1449,7 +1570,7 @@ class CommandObjectCommandsScriptImport : public CommandObjectParsed // Define the first (and only) variant of this arg. cmd_arg.arg_type = eArgTypeFilename; - cmd_arg.arg_repetition = eArgRepeatPlain; + cmd_arg.arg_repetition = eArgRepeatPlus; // There is only one variant this argument could be; put it into the argument entry. arg1.push_back (cmd_arg); @@ -1549,7 +1670,6 @@ class CommandObjectCommandsScriptImport : public CommandObjectParsed bool DoExecute (Args& command, CommandReturnObject &result) { - if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { result.AppendError ("only scripting language supported for module importing is currently Python"); @@ -1558,36 +1678,40 @@ class CommandObjectCommandsScriptImport : public CommandObjectParsed } size_t argc = command.GetArgumentCount(); - - if (argc != 1) + if (0 == argc) { - result.AppendError ("'command script import' requires one argument"); + result.AppendError("command script import needs one or more arguments"); result.SetStatus (eReturnStatusFailed); return false; } - std::string path = command.GetArgumentAtIndex(0); - Error error; - - const bool init_session = true; - // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that - // commands won't ever be recursively invoked, but it's actually possible to craft - // a Python script that does other "command script imports" in __lldb_init_module - // the real fix is to have recursive commands possible with a CommandInvocation object - // separate from the CommandObject itself, so that recursive command invocations - // won't stomp on each other (wrt to execution contents, options, and more) - m_exe_ctx.Clear(); - if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), - m_options.m_allow_reload, - init_session, - error)) + for (size_t i = 0; + i < argc; + i++) { - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); - result.SetStatus (eReturnStatusFailed); + std::string path = command.GetArgumentAtIndex(i); + Error error; + + const bool init_session = true; + // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that + // commands won't ever be recursively invoked, but it's actually possible to craft + // a Python script that does other "command script imports" in __lldb_init_module + // the real fix is to have recursive commands possible with a CommandInvocation object + // separate from the CommandObject itself, so that recursive command invocations + // won't stomp on each other (wrt to execution contents, options, and more) + m_exe_ctx.Clear(); + if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(), + m_options.m_allow_reload, + init_session, + error)) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendErrorWithFormat("module importing failed: %s", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } } return result.Succeeded(); @@ -1652,7 +1776,11 @@ class CommandObjectCommandsScriptAdd : public: CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) + Options (interpreter), + m_class_name(), + m_funct_name(), + m_short_help(), + m_synchronicity(eScriptedCommandSynchronicitySynchronous) { } @@ -1671,6 +1799,10 @@ class CommandObjectCommandsScriptAdd : if (option_arg) m_funct_name.assign(option_arg); break; + case 'c': + if (option_arg) + m_class_name.assign(option_arg); + break; case 'h': if (option_arg) m_short_help.assign(option_arg); @@ -1691,6 +1823,7 @@ class CommandObjectCommandsScriptAdd : void OptionParsingStarting () { + m_class_name.clear(); m_funct_name.clear(); m_short_help.clear(); m_synchronicity = eScriptedCommandSynchronicitySynchronous; @@ -1708,6 +1841,7 @@ class CommandObjectCommandsScriptAdd : // Instance variables to hold the values for command options. + std::string m_class_name; std::string m_funct_name; std::string m_short_help; ScriptedCommandSynchronicity m_synchronicity; @@ -1812,20 +1946,55 @@ class CommandObjectCommandsScriptAdd : m_short_help.assign(m_options.m_short_help); m_synchronicity = m_options.m_synchronicity; - if (m_options.m_funct_name.empty()) + if (m_options.m_class_name.empty()) { - m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + if (m_options.m_funct_name.empty()) + { + m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + } + else + { + CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, + m_cmd_name, + m_options.m_funct_name, + m_options.m_short_help, + m_synchronicity)); + if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError("cannot add command"); + result.SetStatus (eReturnStatusFailed); + } + } } else { - CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, - m_cmd_name, - m_options.m_funct_name, - m_options.m_short_help, - m_synchronicity)); + ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError("cannot find ScriptInterpreter"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str()); + if (!cmd_obj_sp) + { + result.AppendError("cannot create helper object"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter, + m_cmd_name, + cmd_obj_sp, + m_synchronicity)); if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1859,8 +2028,9 @@ OptionDefinition CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, + { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."}, { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."}, - { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, + { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 2ba47be1ecf0..1e575fe963f3 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectDisassemble.h" // C Includes diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index e87399f97baa..f4bb8fbac11e 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectExpression.h" // C Includes @@ -196,7 +194,7 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete "expression", "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.", NULL, - eFlagProcessMustBePaused | eFlagTryTargetAPILock), + eCommandProcessMustBePaused | eCommandTryTargetAPILock), IOHandlerDelegate (IOHandlerDelegate::Completion::Expression), m_option_group (interpreter), m_format_options (eFormatDefault), @@ -487,7 +485,7 @@ CommandObjectExpression::DoExecute if (end_options) { - Args args (command, end_options - command); + Args args (llvm::StringRef(command, end_options - command)); if (!ParseOptions (args, result)) return false; diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp index 4458a692a189..d8b65e3b551a 100644 --- a/source/Commands/CommandObjectFrame.cpp +++ b/source/Commands/CommandObjectFrame.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectFrame.h" // C Includes @@ -65,10 +63,10 @@ class CommandObjectFrameInfo : public CommandObjectParsed "frame info", "List information about the currently selected frame in the current thread.", "frame info", - eFlagRequiresFrame | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ) + eCommandRequiresFrame | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ) { } @@ -156,10 +154,10 @@ class CommandObjectFrameSelect : public CommandObjectParsed "frame select", "Select a frame by index from within the current thread and make it the current frame.", NULL, - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options (interpreter) { CommandArgumentEntry arg; @@ -192,7 +190,7 @@ class CommandObjectFrameSelect : public CommandObjectParsed bool DoExecute (Args& command, CommandReturnObject &result) { - // No need to check "thread" for validity as eFlagRequiresThread ensures it is valid + // No need to check "thread" for validity as eCommandRequiresThread ensures it is valid Thread *thread = m_exe_ctx.GetThreadPtr(); uint32_t frame_idx = UINT32_MAX; @@ -314,11 +312,11 @@ class CommandObjectFrameVariable : public CommandObjectParsed "Children of aggregate variables can be specified such as " "'var->child.x'.", NULL, - eFlagRequiresFrame | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused | - eFlagRequiresProcess), + eCommandRequiresFrame | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused | + eCommandRequiresProcess), m_option_group (interpreter), m_option_variable(true), // Include the frame specific options by passing "true" m_option_format (eFormatDefault), @@ -385,7 +383,7 @@ class CommandObjectFrameVariable : public CommandObjectParsed virtual bool DoExecute (Args& command, CommandReturnObject &result) { - // No need to check "frame" for validity as eFlagRequiresFrame ensures it is valid + // No need to check "frame" for validity as eCommandRequiresFrame ensures it is valid StackFrame *frame = m_exe_ctx.GetFramePtr(); Stream &s = result.GetOutputStream(); @@ -522,30 +520,31 @@ class CommandObjectFrameVariable : public CommandObjectParsed { var_sp = variable_list->GetVariableAtIndex(i); bool dump_variable = true; + std::string scope_string; switch (var_sp->GetScope()) { case eValueTypeVariableGlobal: dump_variable = m_option_variable.show_globals; if (dump_variable && m_option_variable.show_scope) - s.PutCString("GLOBAL: "); + scope_string = "GLOBAL: "; break; case eValueTypeVariableStatic: dump_variable = m_option_variable.show_globals; if (dump_variable && m_option_variable.show_scope) - s.PutCString("STATIC: "); + scope_string = "STATIC: "; break; case eValueTypeVariableArgument: dump_variable = m_option_variable.show_args; if (dump_variable && m_option_variable.show_scope) - s.PutCString(" ARG: "); + scope_string = " ARG: "; break; case eValueTypeVariableLocal: dump_variable = m_option_variable.show_locals; if (dump_variable && m_option_variable.show_scope) - s.PutCString(" LOCAL: "); + scope_string = " LOCAL: "; break; default: @@ -555,7 +554,7 @@ class CommandObjectFrameVariable : public CommandObjectParsed if (dump_variable) { // Use the variable object code to make sure we are - // using the same APIs as the the public API will be + // using the same APIs as the public API will be // using... valobj_sp = frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); @@ -568,6 +567,13 @@ class CommandObjectFrameVariable : public CommandObjectParsed // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope ()) { + if (false == valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && + true == valobj_sp->IsRuntimeSupportValue()) + continue; + + if (!scope_string.empty()) + s.PutCString(scope_string.c_str()); + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); diff --git a/source/Commands/CommandObjectGUI.cpp b/source/Commands/CommandObjectGUI.cpp index 359d6d2892d0..0991c7e84874 100644 --- a/source/Commands/CommandObjectGUI.cpp +++ b/source/Commands/CommandObjectGUI.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectGUI.h" // C Includes diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp index b02515e2d1e8..18dc44a32b5a 100644 --- a/source/Commands/CommandObjectHelp.cpp +++ b/source/Commands/CommandObjectHelp.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectHelp.h" // C Includes diff --git a/source/Commands/CommandObjectLanguage.cpp b/source/Commands/CommandObjectLanguage.cpp new file mode 100644 index 000000000000..9d4b85630a1f --- /dev/null +++ b/source/Commands/CommandObjectLanguage.cpp @@ -0,0 +1,44 @@ +//===-- CommandObjectLanguage.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectLanguage.h" + +#include "lldb/Host/Host.h" + +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" + +#include "lldb/Target/LanguageRuntime.h" + +using namespace lldb; +using namespace lldb_private; + +CommandObjectLanguage::CommandObjectLanguage (CommandInterpreter &interpreter) : +CommandObjectMultiword (interpreter, + "language", + "A set of commands for managing language-specific functionality.'.", + "language []" + ) +{ + //Let the LanguageRuntime populates this command with subcommands + LanguageRuntime::InitializeCommands(this); +} + +void +CommandObjectLanguage::GenerateHelpText (Stream &output_stream) { + CommandObjectMultiword::GenerateHelpText(output_stream); + + output_stream << "\nlanguage name can be one of the following:\n"; + + LanguageRuntime::PrintAllLanguages(output_stream, " ", "\n"); +} + +CommandObjectLanguage::~CommandObjectLanguage () +{ +} diff --git a/source/Commands/CommandObjectLanguage.h b/source/Commands/CommandObjectLanguage.h new file mode 100644 index 000000000000..751fe1440a8b --- /dev/null +++ b/source/Commands/CommandObjectLanguage.h @@ -0,0 +1,41 @@ +//===-- CommandObjectLanguage.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CommandObjectLanguage_h_ +#define liblldb_CommandObjectLanguage_h_ + +// C Includes +// C++ Includes + + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-types.h" +#include "lldb/Interpreter/CommandObjectMultiword.h" + +namespace lldb_private { + class CommandObjectLanguage : public CommandObjectMultiword + { + public: + CommandObjectLanguage (CommandInterpreter &interpreter); + + virtual + ~CommandObjectLanguage (); + + virtual void + GenerateHelpText (Stream &output_stream); + + protected: + bool + DoExecute (Args& command, CommandReturnObject &result); + }; +} // namespace lldb_private + +#endif // liblldb_CommandObjectLanguage_h_ diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp index aa09f53c792b..e68eaf17bb9f 100644 --- a/source/Commands/CommandObjectLog.cpp +++ b/source/Commands/CommandObjectLog.cpp @@ -7,16 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectLog.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-log.h" - #include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h" #include "lldb/Host/FileSpec.h" @@ -148,6 +144,7 @@ class CommandObjectLogEnable : public CommandObjectParsed case 'p': log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break; case 'n': log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; break; case 'S': log_options |= LLDB_LOG_OPTION_BACKTRACE; break; + case 'a': log_options |= LLDB_LOG_OPTION_APPEND; break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); break; @@ -225,6 +222,7 @@ CommandObjectLogEnable::CommandOptions::g_option_table[] = { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, { LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, { LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, +{ LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Append to the log file instead of overwriting." }, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index dac6dd81651b..d589800299a3 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectMemory.h" // C Includes @@ -16,6 +14,7 @@ // C++ Includes // Other libraries and framework includes +#include "clang/AST/Decl.h" // Project includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" @@ -24,6 +23,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -95,7 +95,7 @@ class OptionGroupReadMemory : public OptionGroup switch (short_option) { case 'l': - error = m_num_per_line.SetValueFromCString (option_arg); + error = m_num_per_line.SetValueFromString (option_arg); if (m_num_per_line.GetCurrentValue() == 0) error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg); break; @@ -105,7 +105,7 @@ class OptionGroupReadMemory : public OptionGroup break; case 't': - error = m_view_as_type.SetValueFromCString (option_arg); + error = m_view_as_type.SetValueFromString (option_arg); break; case 'r': @@ -313,7 +313,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed "memory read", "Read from the memory of the process being debugged.", NULL, - eFlagRequiresTarget | eFlagProcessMustBePaused), + eCommandRequiresTarget | eCommandProcessMustBePaused), m_option_group (interpreter), m_format_options (eFormatBytesWithASCII, 1, 8), m_memory_options (), @@ -386,7 +386,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed virtual bool DoExecute (Args& command, CommandReturnObject &result) { - // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid + // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid Target *target = m_exe_ctx.GetTargetPtr(); const size_t argc = command.GetArgumentCount(); @@ -532,7 +532,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); if (tdecl) { - clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl()); + clang_ast_type.SetClangType(&tdecl->getASTContext(),(const lldb::clang_type_t)tdecl->getTypeForDecl()); } } @@ -742,6 +742,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed auto data_addr = addr; auto count = item_count; item_count = 0; + bool break_on_no_NULL = false; while (item_count < count) { std::string buffer; @@ -754,17 +755,24 @@ class CommandObjectMemoryRead : public CommandObjectParsed result.SetStatus(eReturnStatusFailed); return false; } + if (item_byte_size == read) { result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr); - break; + --read; + break_on_no_NULL = true; } - read+=1; // account for final NULL byte + else + ++read; // account for final NULL byte + memcpy(data_ptr, &buffer[0], read); data_ptr += read; data_addr += read; bytes_read += read; item_count++; // if we break early we know we only read item_count strings + + if (break_on_no_NULL) + break; } data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1)); } @@ -981,20 +989,20 @@ class CommandObjectMemoryFind : public CommandObjectParsed switch (short_option) { case 'e': - m_expr.SetValueFromCString(option_arg); + m_expr.SetValueFromString(option_arg); break; case 's': - m_string.SetValueFromCString(option_arg); + m_string.SetValueFromString(option_arg); break; case 'c': - if (m_count.SetValueFromCString(option_arg).Fail()) + if (m_count.SetValueFromString(option_arg).Fail()) error.SetErrorString("unrecognized value for count"); break; case 'o': - if (m_offset.SetValueFromCString(option_arg).Fail()) + if (m_offset.SetValueFromString(option_arg).Fail()) error.SetErrorString("unrecognized value for dump-offset"); break; @@ -1024,7 +1032,7 @@ class CommandObjectMemoryFind : public CommandObjectParsed "memory find", "Find a value in the memory of the process being debugged.", NULL, - eFlagRequiresProcess | eFlagProcessMustBeLaunched), + eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_option_group (interpreter), m_memory_options () { @@ -1070,7 +1078,7 @@ class CommandObjectMemoryFind : public CommandObjectParsed virtual bool DoExecute (Args& command, CommandReturnObject &result) { - // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid + // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); const size_t argc = command.GetArgumentCount(); @@ -1325,7 +1333,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed "memory write", "Write to the memory of the process being debugged.", NULL, - eFlagRequiresProcess | eFlagProcessMustBeLaunched), + eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_option_group (interpreter), m_format_options (eFormatBytes, 1, UINT64_MAX), m_memory_options () @@ -1402,7 +1410,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed virtual bool DoExecute (Args& command, CommandReturnObject &result) { - // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid + // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); const size_t argc = command.GetArgumentCount(); @@ -1692,7 +1700,7 @@ class CommandObjectMemoryHistory : public CommandObjectParsed "memory history", "Prints out the recorded stack traces for allocation/deallocation of a memory address.", NULL, - eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched) + eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched) { CommandArgumentEntry arg1; CommandArgumentData addr_arg; diff --git a/source/Commands/CommandObjectMultiword.cpp b/source/Commands/CommandObjectMultiword.cpp index 69b178da46ba..2f0e2a78a0cc 100644 --- a/source/Commands/CommandObjectMultiword.cpp +++ b/source/Commands/CommandObjectMultiword.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/Interpreter/CommandObjectMultiword.h" // C Includes // C++ Includes @@ -153,7 +151,7 @@ CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &re error_msg.append (GetCommandName()); error_msg.append (" "); error_msg.append (sub_command); - error_msg.append ("'"); + error_msg.append ("'."); if (num_subcmd_matches > 0) { @@ -251,23 +249,27 @@ CommandObjectMultiword::HandleCompletion &temp_matches); if (cmd_obj != NULL) { - matches.DeleteStringAtIndex (0); - input.Shift(); - cursor_char_position = 0; - input.AppendArgument (""); - return cmd_obj->HandleCompletion (input, - cursor_index, - cursor_char_position, - match_start_point, - max_return_elements, - word_complete, - matches); + if (input.GetArgumentCount() == 1) + { + word_complete = true; + } + else + { + matches.DeleteStringAtIndex (0); + input.Shift(); + cursor_char_position = 0; + input.AppendArgument (""); + return cmd_obj->HandleCompletion (input, + cursor_index, + cursor_char_position, + match_start_point, + max_return_elements, + word_complete, + matches); + } } - else - return matches.GetSize(); } - else - return matches.GetSize(); + return matches.GetSize(); } else { diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index 959c5cd1d0d7..866587fb4ebc 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectPlatform.h" // C Includes @@ -558,7 +556,7 @@ class CommandObjectPlatformSettings : public CommandObjectParsed if (platform_sp) { if (m_option_working_dir.GetOptionValue().OptionWasSet()) - platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str())); + platform_sp->SetWorkingDirectory(m_option_working_dir.GetOptionValue().GetCurrentValue()); } else { @@ -572,10 +570,7 @@ class CommandObjectPlatformSettings : public CommandObjectParsed GetOptions () { if (m_options.DidFinalize() == false) - { - m_options.Append(new OptionPermissions()); m_options.Finalize(); - } return &m_options; } protected: @@ -621,7 +616,7 @@ class CommandObjectPlatformMkDir : public CommandObjectParsed mode = options_permissions->m_permissions; else mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX; - Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode); + Error error = platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode); if (error.Success()) { result.SetStatus (eReturnStatusSuccessFinishResult); @@ -1201,7 +1196,7 @@ class CommandObjectPlatformGetSize : public CommandObjectParsed } else { - result.AppendMessageWithFormat("Eroor getting file size of %s (remote)\n", remote_file_path.c_str()); + result.AppendMessageWithFormat("Error getting file size of %s (remote)\n", remote_file_path.c_str()); result.SetStatus (eReturnStatusFailed); } } @@ -1241,8 +1236,8 @@ class CommandObjectPlatformPutFile : public CommandObjectParsed const char* dst = args.GetArgumentAtIndex(1); FileSpec src_fs(src, true); - FileSpec dst_fs(dst, false); - + FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false); + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) { @@ -1277,7 +1272,7 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed "platform process launch", "Launch a new process on a remote platform.", "platform process launch program", - eFlagRequiresTarget | eFlagTryTargetAPILock), + eCommandRequiresTarget | eCommandTryTargetAPILock), m_options (interpreter) { } @@ -1975,7 +1970,7 @@ CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "plugin", 'P' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, { LLDB_OPT_SET_1, false, "pid", 'p' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, { LLDB_OPT_SET_2, false, "name", 'n' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, - { LLDB_OPT_SET_2, false, "waitfor", 'w' , OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Wait for the the process with to launch."}, + { LLDB_OPT_SET_2, false, "waitfor", 'w' , OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Wait for the process with to launch."}, { 0, false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -2085,7 +2080,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw CommandObjectPlatformShell (CommandInterpreter &interpreter) : CommandObjectRaw (interpreter, "platform shell", - "Run a shell command on a the selected platform.", + "Run a shell command on the selected platform.", "platform shell ", 0), m_options(interpreter) @@ -2142,7 +2137,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw if (end_options) { - Args args (raw_command_line, end_options - raw_command_line); + Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); if (!ParseOptions (args, result)) return false; } @@ -2155,7 +2150,7 @@ class CommandObjectPlatformShell : public CommandObjectRaw Error error; if (platform_sp) { - const char *working_dir = NULL; + FileSpec working_dir{}; std::string output; int status = -1; int signo = -1; diff --git a/source/Commands/CommandObjectPlugin.cpp b/source/Commands/CommandObjectPlugin.cpp index 658c077bc3ea..63fa4a82cf91 100644 --- a/source/Commands/CommandObjectPlugin.cpp +++ b/source/Commands/CommandObjectPlugin.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectPlugin.h" #include "lldb/Host/Host.h" diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index d47311e5cb5f..4414bdf2a2c8 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectProcess.h" // C Includes @@ -32,6 +30,7 @@ #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/UnixSignals.h" using namespace lldb; using namespace lldb_private; @@ -92,7 +91,7 @@ class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed } else { - Error destroy_error (process->Destroy()); + Error destroy_error (process->Destroy(false)); if (destroy_error.Success()) { result.SetStatus (eReturnStatusSuccessFinishResult); @@ -124,7 +123,7 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach "process launch", "Launch the executable in the debugger.", NULL, - eFlagRequiresTarget, + eCommandRequiresTarget, "restart"), m_options (interpreter) { @@ -249,9 +248,7 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach if (launch_args.GetArgumentCount() == 0) { - Args target_setting_args; - if (target->GetRunArguments(target_setting_args)) - m_options.launch_info.GetArguments().AppendArguments (target_setting_args); + m_options.launch_info.GetArguments().AppendArguments (target->GetProcessLaunchInfo().GetArguments()); } else { @@ -265,13 +262,18 @@ class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach if (error.Success()) { - const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName(); ProcessSP process_sp (target->GetProcessSP()); if (process_sp) { + // There is a race condition where this thread will return up the call stack to the main command + // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has + // a chance to call PushProcessIOHandler(). + process_sp->SyncIOHandler (0, 2000); + const char *data = stream.GetData(); if (data && strlen(data) > 0) result.AppendMessage(stream.GetData()); + const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName(); result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname); result.SetStatus (eReturnStatusSuccessFinishResult); result.SetDidChangeProcessState (true); @@ -529,8 +531,6 @@ class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach ModuleSP old_exec_module_sp = target->GetExecutableModule(); ArchSpec old_arch_spec = target->GetArchitecture(); - ProcessSP process_sp; - Error error; if (command.GetArgumentCount()) { result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); @@ -539,70 +539,21 @@ class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach } m_interpreter.UpdateExecutionContext(nullptr); - ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack")); - m_options.attach_info.SetHijackListener(listener_sp); - - // If no process info was specified, then use the target executable - // name as the process to attach to by default - if (!m_options.attach_info.ProcessInfoSpecified ()) - { - if (old_exec_module_sp) - m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename(); - - if (!m_options.attach_info.ProcessInfoSpecified ()) - { - error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option"); - } - } - + StreamString stream; + const auto error = target->Attach(m_options.attach_info, &stream); if (error.Success()) { - if (state != eStateConnected && platform_sp != nullptr && platform_sp->CanDebugProcess()) - { - target->SetPlatform(platform_sp); - process = platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), target, error).get(); - } - else - { - if (state != eStateConnected) - { - const char *plugin_name = m_options.attach_info.GetProcessPluginName(); - process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, nullptr).get(); - if (process == nullptr) - error.SetErrorStringWithFormat("failed to create process using plugin %s", plugin_name); - } - if (process) - { - process->HijackProcessEvents(listener_sp.get()); - error = process->Attach(m_options.attach_info); - } - } - } - - if (error.Success() && process != nullptr) - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - StreamString stream; - StateType state = process->WaitForProcessToStop (nullptr, nullptr, false, listener_sp.get(), &stream); - - process->RestoreProcessEvents(); - result.SetDidChangeProcessState (true); - - if (stream.GetData()) - result.AppendMessage(stream.GetData()); - - if (state == eStateStopped) + ProcessSP process_sp (target->GetProcessSP()); + if (process_sp) { + if (stream.GetData()) + result.AppendMessage(stream.GetData()); result.SetStatus (eReturnStatusSuccessFinishNoResult); + result.SetDidChangeProcessState (true); } else { - const char *exit_desc = process->GetExitDescription(); - if (exit_desc) - result.AppendErrorWithFormat ("attach failed: %s", exit_desc); - else - result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); - process->Destroy(); + result.AppendError("no error returned from Target::Attach, and target has no process"); result.SetStatus (eReturnStatusFailed); } } @@ -686,10 +637,10 @@ class CommandObjectProcessContinue : public CommandObjectParsed "process continue", "Continue execution of all threads in the current process.", "process continue", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options(interpreter) { } @@ -809,6 +760,8 @@ class CommandObjectProcessContinue : public CommandObjectParsed } } + const uint32_t iohandler_id = process->GetIOHandlerID(); + StreamString stream; Error error; if (synchronous_execution) @@ -819,9 +772,9 @@ class CommandObjectProcessContinue : public CommandObjectParsed if (error.Success()) { // There is a race condition where this thread will return up the call stack to the main command - // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has - // a chance to call PushProcessIOHandler(). - process->SyncIOHandler(2000); + // handler and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has + // a chance to call PushProcessIOHandler(). + process->SyncIOHandler(iohandler_id, 2000); result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); if (synchronous_execution) @@ -947,9 +900,9 @@ class CommandObjectProcessDetach : public CommandObjectParsed "process detach", "Detach from the current process being debugged.", "process detach", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched), + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched), m_options(interpreter) { } @@ -1228,10 +1181,10 @@ class CommandObjectProcessLoad : public CommandObjectParsed "process load", "Load a shared library into the current process.", "process load [ ...]", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ) { } @@ -1285,10 +1238,10 @@ class CommandObjectProcessUnload : public CommandObjectParsed "process unload", "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", "process unload ", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ) { } @@ -1349,7 +1302,7 @@ class CommandObjectProcessSignal : public CommandObjectParsed "process signal", "Send a UNIX signal to the current process being debugged.", NULL, - eFlagRequiresProcess | eFlagTryTargetAPILock) + eCommandRequiresProcess | eCommandTryTargetAPILock) { CommandArgumentEntry arg; CommandArgumentData signal_arg; @@ -1431,9 +1384,9 @@ class CommandObjectProcessInterrupt : public CommandObjectParsed "process interrupt", "Interrupt the current process being debugged.", "process interrupt", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched) { } @@ -1493,9 +1446,9 @@ class CommandObjectProcessKill : public CommandObjectParsed "process kill", "Terminate the current process being debugged.", "process kill", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched) { } @@ -1518,7 +1471,7 @@ class CommandObjectProcessKill : public CommandObjectParsed if (command.GetArgumentCount() == 0) { - Error error (process->Destroy()); + Error error (process->Destroy(true)); if (error.Success()) { result.SetStatus (eReturnStatusSuccessFinishResult); @@ -1554,9 +1507,9 @@ class CommandObjectProcessSaveCore : public CommandObjectParsed "process save-core", "Save the current process as a core file using an appropriate file type.", "process save-core FILE", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched) { } @@ -1618,7 +1571,7 @@ class CommandObjectProcessStatus : public CommandObjectParsed "process status", "Show the current status and location of executing process.", "process status", - eFlagRequiresProcess | eFlagTryTargetAPILock) + eCommandRequiresProcess | eCommandTryTargetAPILock) { } @@ -1632,7 +1585,7 @@ class CommandObjectProcessStatus : public CommandObjectParsed { Stream &strm = result.GetOutputStream(); result.SetStatus (eReturnStatusSuccessFinishNoResult); - // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid + // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); const bool only_threads_with_stop_reason = true; const uint32_t start_frame = 0; @@ -1776,8 +1729,8 @@ class CommandObjectProcessHandle : public CommandObjectParsed void PrintSignalHeader (Stream &str) { - str.Printf ("NAME PASS STOP NOTIFY\n"); - str.Printf ("========== ===== ===== ======\n"); + str.Printf ("NAME PASS STOP NOTIFY\n"); + str.Printf ("=========== ===== ===== ======\n"); } void @@ -1787,7 +1740,7 @@ class CommandObjectProcessHandle : public CommandObjectParsed bool suppress; bool notify; - str.Printf ("%-10s ", sig_name); + str.Printf ("%-11s ", sig_name); if (signals.GetSignalInfo (signo, suppress, stop, notify)) { bool pass = !suppress; diff --git a/source/Commands/CommandObjectQuit.cpp b/source/Commands/CommandObjectQuit.cpp index dd0efc61b2d0..31f82b987c1c 100644 --- a/source/Commands/CommandObjectQuit.cpp +++ b/source/Commands/CommandObjectQuit.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectQuit.h" // C Includes @@ -17,6 +15,7 @@ // Project includes #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/Process.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp index 81b79b8cd8b2..fae5af42f405 100644 --- a/source/Commands/CommandObjectRegister.cpp +++ b/source/Commands/CommandObjectRegister.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectRegister.h" // C Includes @@ -25,6 +23,7 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionValueArray.h" +#include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -47,10 +46,10 @@ class CommandObjectRegisterRead : public CommandObjectParsed "register read", "Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.", NULL, - eFlagRequiresFrame | - eFlagRequiresRegContext | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresFrame | + eCommandRequiresRegContext | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_option_group (interpreter), m_format_options (eFormatDefault), m_command_options () @@ -143,7 +142,7 @@ class CommandObjectRegisterRead : public CommandObjectParsed const RegisterSet * const reg_set = reg_ctx->GetRegisterSet(set_idx); if (reg_set) { - strm.Printf ("%s:\n", reg_set->name); + strm.Printf ("%s:\n", (reg_set->name ? reg_set->name : "unknown") ); strm.IndentMore (); const size_t num_registers = reg_set->num_registers; for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) @@ -376,10 +375,10 @@ class CommandObjectRegisterWrite : public CommandObjectParsed "register write", "Modify a single register value.", NULL, - eFlagRequiresFrame | - eFlagRequiresRegContext | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused) + eCommandRequiresFrame | + eCommandRequiresRegContext | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused) { CommandArgumentEntry arg1; CommandArgumentEntry arg2; diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp index ed677afabcb5..ccbf98c767f1 100644 --- a/source/Commands/CommandObjectSettings.cpp +++ b/source/Commands/CommandObjectSettings.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectSettings.h" // C Includes @@ -18,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Interpreter/OptionValueProperties.h" using namespace lldb; using namespace lldb_private; @@ -243,7 +242,7 @@ insert-before or insert-after.\n"); // Split the raw command into var_name and value pair. llvm::StringRef raw_str(command); std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false); + const char *var_value_cstr = Args::StripSpaces(var_value_string, true, false, false); Error error; if (m_options.m_global) diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index a88a9b1f0cac..7c5f127cb51a 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectSource.h" // C Includes @@ -253,7 +251,7 @@ class CommandObjectSourceList : public CommandObjectParsed "source list", "Display source code (as specified) based on the current executable's debug info.", NULL, - eFlagRequiresTarget), + eCommandRequiresTarget), m_options (interpreter) { } @@ -539,9 +537,9 @@ class CommandObjectSourceList : public CommandObjectParsed { SymbolContext sc; sc_list_symbols.GetContextAtIndex (i, sc); - if (sc.symbol) + if (sc.symbol && sc.symbol->ValueIsAddress()) { - const Address &base_address = sc.symbol->GetAddress(); + const Address &base_address = sc.symbol->GetAddressRef(); Function *function = base_address.CalculateSymbolContextFunction(); if (function) { @@ -690,13 +688,15 @@ class CommandObjectSourceList : public CommandObjectParsed bool show_module = true; bool show_inlined_frames = true; const bool show_function_arguments = true; + const bool show_function_name = true; sc.DumpStopContext(&result.GetOutputStream(), m_exe_ctx.GetBestExecutionContextScope(), sc.line_entry.range.GetBaseAddress(), show_fullpaths, show_module, show_inlined_frames, - show_function_arguments); + show_function_arguments, + show_function_name); result.GetOutputStream().EOL(); if (m_options.num_lines == 0) diff --git a/source/Commands/CommandObjectSyntax.cpp b/source/Commands/CommandObjectSyntax.cpp index 5093c3b99339..e9fa084fc0b5 100644 --- a/source/Commands/CommandObjectSyntax.cpp +++ b/source/Commands/CommandObjectSyntax.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectSyntax.h" // C Includes diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index 9188283966f1..448da0ede245 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectTarget.h" // C Includes @@ -50,6 +48,7 @@ #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" @@ -388,6 +387,12 @@ class CommandObjectTargetCreate : public CommandObjectParsed core_file.GetPath(core_path, sizeof(core_path)); if (core_file.Exists()) { + if (!core_file.Readable()) + { + result.AppendMessageWithFormat ("Core file '%s' is not readable.\n", core_path); + result.SetStatus (eReturnStatusFailed); + return false; + } FileSpec core_file_dir; core_file_dir.GetDirectory() = core_file.GetDirectory(); target_sp->GetExecutableSearchPaths ().Append (core_file_dir); @@ -600,10 +605,20 @@ class CommandObjectTargetDelete : public CommandObjectParsed "Delete one or more targets by target index.", NULL, 0), - m_option_group (interpreter), - m_cleanup_option (LLDB_OPT_SET_1, false, "clean", 'c', "Perform extra cleanup to minimize memory consumption after deleting the target.", false, false) + m_option_group(interpreter), + m_all_option(LLDB_OPT_SET_1, false, "all", 'a', "Delete all targets.", false, true), + m_cleanup_option( + LLDB_OPT_SET_1, + false, + "clean", 'c', + "Perform extra cleanup to minimize memory consumption after deleting the target. " + "By default, LLDB will keep in memory any modules previously loaded by the target as well " + "as all of its debug info. Specifying --clean will unload all of these shared modules and " + "cause them to be reparsed again the next time the target is run", + false, true) { - m_option_group.Append (&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); } @@ -625,90 +640,89 @@ class CommandObjectTargetDelete : public CommandObjectParsed const size_t argc = args.GetArgumentCount(); std::vector delete_target_list; TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); - bool success = true; TargetSP target_sp; - if (argc > 0) + + if (m_all_option.GetOptionValue()) + { + for (int i = 0; i < target_list.GetNumTargets(); ++i) + delete_target_list.push_back(target_list.GetTargetAtIndex(i)); + } + else if (argc > 0) { const uint32_t num_targets = target_list.GetNumTargets(); // Bail out if don't have any targets. if (num_targets == 0) { result.AppendError("no targets to delete"); result.SetStatus(eReturnStatusFailed); - success = false; + return false; } - for (uint32_t arg_idx = 0; success && arg_idx < argc; ++arg_idx) + for (uint32_t arg_idx = 0; arg_idx < argc; ++arg_idx) { const char *target_idx_arg = args.GetArgumentAtIndex(arg_idx); + bool success = false; uint32_t target_idx = StringConvert::ToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); - if (success) - { - if (target_idx < num_targets) - { - target_sp = target_list.GetTargetAtIndex (target_idx); - if (target_sp) - { - delete_target_list.push_back (target_sp); - continue; - } - } - if (num_targets > 1) - result.AppendErrorWithFormat ("target index %u is out of range, valid target indexes are 0 - %u\n", - target_idx, - num_targets - 1); - else - result.AppendErrorWithFormat("target index %u is out of range, the only valid index is 0\n", - target_idx); - - result.SetStatus (eReturnStatusFailed); - success = false; - } - else + if (!success) { result.AppendErrorWithFormat("invalid target index '%s'\n", target_idx_arg); result.SetStatus (eReturnStatusFailed); - success = false; + return false; } + if (target_idx < num_targets) + { + target_sp = target_list.GetTargetAtIndex (target_idx); + if (target_sp) + { + delete_target_list.push_back (target_sp); + continue; + } + } + if (num_targets > 1) + result.AppendErrorWithFormat ("target index %u is out of range, valid target indexes are 0 - %u\n", + target_idx, + num_targets - 1); + else + result.AppendErrorWithFormat("target index %u is out of range, the only valid index is 0\n", + target_idx); + + result.SetStatus (eReturnStatusFailed); + return false; } } else { target_sp = target_list.GetSelectedTarget(); - if (target_sp) - { - delete_target_list.push_back (target_sp); - } - else + if (!target_sp) { result.AppendErrorWithFormat("no target is currently selected\n"); result.SetStatus (eReturnStatusFailed); - success = false; + return false; } - } - if (success) - { - const size_t num_targets_to_delete = delete_target_list.size(); - for (size_t idx = 0; idx < num_targets_to_delete; ++idx) - { - target_sp = delete_target_list[idx]; - target_list.DeleteTarget(target_sp); - target_sp->Destroy(); - } - // If "--clean" was specified, prune any orphaned shared modules from - // the global shared module list - if (m_cleanup_option.GetOptionValue ()) - { - const bool mandatory = true; - ModuleList::RemoveOrphanSharedModules(mandatory); - } - result.GetOutputStream().Printf("%u targets deleted.\n", (uint32_t)num_targets_to_delete); - result.SetStatus(eReturnStatusSuccessFinishResult); + delete_target_list.push_back (target_sp); } - return result.Succeeded(); + const size_t num_targets_to_delete = delete_target_list.size(); + for (size_t idx = 0; idx < num_targets_to_delete; ++idx) + { + target_sp = delete_target_list[idx]; + target_list.DeleteTarget(target_sp); + target_sp->Destroy(); + } + // If "--clean" was specified, prune any orphaned shared modules from + // the global shared module list + if (m_cleanup_option.GetOptionValue ()) + { + const bool mandatory = true; + ModuleList::RemoveOrphanSharedModules(mandatory); + } + result.GetOutputStream().Printf("%u targets deleted.\n", (uint32_t)num_targets_to_delete); + result.SetStatus(eReturnStatusSuccessFinishResult); + + return true; } OptionGroupOptions m_option_group; + OptionGroupBoolean m_all_option; OptionGroupBoolean m_cleanup_option; }; @@ -730,7 +744,7 @@ class CommandObjectTargetVariable : public CommandObjectParsed "target variable", "Read global variable(s) prior to, or while running your binary.", NULL, - eFlagRequiresTarget), + eCommandRequiresTarget), m_option_group (interpreter), m_option_variable (false), // Don't include frame options m_option_format (eFormatDefault), @@ -773,6 +787,10 @@ class CommandObjectTargetVariable : public CommandObjectParsed { DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); + if (false == valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() && + true == valobj_sp->IsRuntimeSupportValue()) + return; + switch (var_sp->GetScope()) { case eValueTypeVariableGlobal: @@ -1722,17 +1740,16 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod DumpFullpath (strm, &module->GetFileSpec(), 0); strm.PutCString(":\n"); strm.IndentMore (); - //Symtab::DumpSymbolHeader (&strm); for (i=0; i < num_matches; ++i) { Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); - DumpAddress (interpreter.GetExecutionContext().GetBestExecutionContextScope(), - symbol->GetAddress(), - verbose, - strm); - -// strm.Indent (); -// symbol->Dump (&strm, interpreter.GetExecutionContext().GetTargetPtr(), i); + if (symbol && symbol->ValueIsAddress()) + { + DumpAddress (interpreter.GetExecutionContext().GetBestExecutionContextScope(), + symbol->GetAddressRef(), + verbose, + strm); + } } strm.IndentLess (); return num_matches; @@ -2547,7 +2564,7 @@ class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModule "target modules dump line-table", "Dump the line table for one or more compilation units.", NULL, - eFlagRequiresTarget) + eCommandRequiresTarget) { } @@ -3462,28 +3479,24 @@ class CommandObjectTargetModulesList : public CommandObjectParsed case 's': case 'S': { - SymbolVendor *symbol_vendor = module->GetSymbolVendor(); + const SymbolVendor *symbol_vendor = module->GetSymbolVendor(); if (symbol_vendor) { - SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); - if (symbol_file) + const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec(); + if (format_char == 'S') { - if (format_char == 'S') + // Dump symbol file only if different from module file + if (!symfile_spec || symfile_spec == module->GetFileSpec()) { - FileSpec &symfile_spec = symbol_file->GetObjectFile()->GetFileSpec(); - // Dump symbol file only if different from module file - if (!symfile_spec || symfile_spec == module->GetFileSpec()) - { - print_space = false; - break; - } - // Add a newline and indent past the index - strm.Printf ("\n%*s", indent, ""); + print_space = false; + break; } - DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width); - dump_object_name = true; - break; + // Add a newline and indent past the index + strm.Printf ("\n%*s", indent, ""); } + DumpFullpath (strm, &symfile_spec, width); + dump_object_name = true; + break; } strm.Printf("%.*s", width, ""); } @@ -3641,10 +3654,10 @@ class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed "target modules show-unwind", "Show synthesized unwind instructions for a function.", NULL, - eFlagRequiresTarget | - eFlagRequiresProcess | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresTarget | + eCommandRequiresProcess | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options (interpreter) { } @@ -3767,7 +3780,7 @@ class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed { result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", callsite_unwind_plan->GetSourceName().AsCString()); } - UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get()); + UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread.get()); if (fast_unwind_plan.get()) { result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n", fast_unwind_plan->GetSourceName().AsCString()); @@ -4001,7 +4014,7 @@ class CommandObjectTargetModulesLookup : public CommandObjectParsed "target modules lookup", "Look up information within executable and dependent shared library images.", NULL, - eFlagRequiresTarget), + eCommandRequiresTarget), m_options (interpreter) { CommandArgumentEntry arg; @@ -4381,7 +4394,7 @@ class CommandObjectTargetSymbolsAdd : public CommandObjectParsed CommandObjectParsed (interpreter, "target symbols add", "Add a debug symbol file to one of the target's current modules by specifying a path to a debug symbols file, or using the options to specify a module to download symbols for.", - "target symbols add []", eFlagRequiresTarget), + "target symbols add []", eCommandRequiresTarget), m_option_group (interpreter), m_file_option (LLDB_OPT_SET_1, false, "shlib", 's', CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Fullpath or basename for module to find debug symbols for."), m_current_frame_option (LLDB_OPT_SET_2, false, "frame", 'F', "Locate the debug symbols the currently selected frame.", false, true) diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index 199d16b85205..5f38ad4900d6 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectThread.h" // C Includes @@ -18,6 +16,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/State.h" #include "lldb/Core/SourceManager.h" +#include "lldb/Core/ValueObject.h" #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -240,11 +239,11 @@ class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads "thread backtrace", "Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.", NULL, - eFlagRequiresProcess | - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresProcess | + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options(interpreter) { } @@ -432,6 +431,12 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed m_step_in_avoid_no_debug = eLazyBoolCalculate; m_step_out_avoid_no_debug = eLazyBoolCalculate; m_run_mode = eOnlyDuringStepping; + + // Check if we are in Non-Stop mode + lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); + if (target_sp.get() != nullptr && target_sp->GetNonStopModeEnabled()) + m_run_mode = eOnlyThisThread; + m_avoid_regexp.clear(); m_step_in_target.clear(); m_class_name.clear(); @@ -465,11 +470,11 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed StepType step_type, StepScope step_scope) : CommandObjectParsed (interpreter, name, help, syntax, - eFlagRequiresProcess | - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresProcess | + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_step_type (step_type), m_step_scope (step_scope), m_options (interpreter) @@ -579,6 +584,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed if (m_step_type == eStepTypeInto) { StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); + assert(frame != nullptr); if (frame->HasDebugInformation ()) { @@ -667,6 +673,8 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed process->GetThreadList().SetSelectedThreadByID (thread->GetID()); + const uint32_t iohandler_id = process->GetIOHandlerID(); + StreamString stream; Error error; if (synchronous_execution) @@ -677,7 +685,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed // There is a race condition where this thread will return up the call stack to the main command handler // and show an (lldb) prompt before HandlePrivateEvent (from PrivateStateThread) has // a chance to call PushProcessIOHandler(). - process->SyncIOHandler(2000); + process->SyncIOHandler(iohandler_id, 2000); if (synchronous_execution) { @@ -752,10 +760,10 @@ class CommandObjectThreadContinue : public CommandObjectParsed "thread continue", "Continue execution of one or more threads in an active process.", NULL, - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused) + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused) { CommandArgumentEntry arg; CommandArgumentData thread_idx_arg; @@ -1064,10 +1072,10 @@ class CommandObjectThreadUntil : public CommandObjectParsed "thread until", "Run the current or specified thread until it reaches a given line number or address or leaves the current function.", NULL, - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options (interpreter) { CommandArgumentEntry arg; @@ -1343,10 +1351,10 @@ class CommandObjectThreadSelect : public CommandObjectParsed "thread select", "Select a thread as the currently active thread.", NULL, - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ) { CommandArgumentEntry arg; CommandArgumentData thread_idx_arg; @@ -1419,10 +1427,10 @@ class CommandObjectThreadList : public CommandObjectParsed "thread list", "Show a summary of all current threads in a process.", "thread list", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ) + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ) { } @@ -1464,10 +1472,10 @@ class CommandObjectThreadInfo : public CommandObjectIterateOverThreads "thread info", "Show an extended summary of information about thread(s) in a process.", "thread info", - eFlagRequiresProcess | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused), + eCommandRequiresProcess | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), m_options (interpreter) { m_add_return = false; @@ -1656,10 +1664,10 @@ class CommandObjectThreadReturn : public CommandObjectRaw "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value," " or with the -x option from the innermost function evaluation.", "thread return", - eFlagRequiresFrame | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresFrame | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options (interpreter) { CommandArgumentEntry arg; @@ -1884,10 +1892,10 @@ class CommandObjectThreadJump : public CommandObjectParsed "thread jump", "Sets the program counter to a new address.", "thread jump", - eFlagRequiresFrame | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresFrame | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options (interpreter) { } @@ -2068,11 +2076,11 @@ class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads "Show thread plans for one or more threads. If no threads are specified, show the " "currently selected thread. Use the thread-index \"all\" to see all threads.", NULL, - eFlagRequiresProcess | - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresProcess | + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_options(interpreter) { } @@ -2120,11 +2128,11 @@ class CommandObjectThreadPlanDiscard : public CommandObjectParsed "Only user visible plans can be discarded, use the index from \"thread plan list\"" " without the \"-i\" argument.", NULL, - eFlagRequiresProcess | - eFlagRequiresThread | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ) + eCommandRequiresProcess | + eCommandRequiresThread | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ) { CommandArgumentEntry arg; CommandArgumentData plan_index_arg; diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp index 3a4c60c00f8b..7c8061a6ca08 100644 --- a/source/Commands/CommandObjectType.cpp +++ b/source/Commands/CommandObjectType.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectType.h" // C Includes @@ -4249,7 +4247,7 @@ class CommandObjectFormatterInfo : public CommandObjectRaw nullptr, nullptr, nullptr, - eFlagRequiresFrame), + eCommandRequiresFrame), m_formatter_name(formatter_name ? formatter_name : ""), m_discovery_function(discovery_func) { diff --git a/source/Commands/CommandObjectVersion.cpp b/source/Commands/CommandObjectVersion.cpp index 2d950a89c9b3..70e101c22330 100644 --- a/source/Commands/CommandObjectVersion.cpp +++ b/source/Commands/CommandObjectVersion.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectVersion.h" // C Includes diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp index bef59ca30b3c..650fd253af02 100644 --- a/source/Commands/CommandObjectWatchpoint.cpp +++ b/source/Commands/CommandObjectWatchpoint.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "CommandObjectWatchpoint.h" #include "CommandObjectWatchpointCommand.h" @@ -27,6 +25,7 @@ #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "llvm/ADT/StringRef.h" @@ -924,10 +923,10 @@ class CommandObjectWatchpointSetVariable : public CommandObjectParsed "If watchpoint setting fails, consider disable/delete existing ones " "to free up resources.", NULL, - eFlagRequiresFrame | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresFrame | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_option_group (interpreter), m_option_watchpoint () { @@ -1131,10 +1130,10 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw "If watchpoint setting fails, consider disable/delete existing ones " "to free up resources.", NULL, - eFlagRequiresFrame | - eFlagTryTargetAPILock | - eFlagProcessMustBeLaunched | - eFlagProcessMustBePaused ), + eCommandRequiresFrame | + eCommandTryTargetAPILock | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused ), m_option_group (interpreter), m_option_watchpoint () { @@ -1211,7 +1210,7 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw if (end_options) { - Args args (raw_command, end_options - raw_command); + Args args (llvm::StringRef(raw_command, end_options - raw_command)); if (!ParseOptions (args, result)) return false; diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp index 275ee925adcc..d7d064e5fed9 100644 --- a/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/source/Commands/CommandObjectWatchpointCommand.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - // C Includes // C++ Includes diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index d449d0b21438..1cd7a7447b7f 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -468,6 +468,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum case DumpStyleResolvedDescription: case DumpStyleResolvedDescriptionNoModule: case DumpStyleResolvedDescriptionNoFunctionArguments: + case DumpStyleNoFunctionName: if (IsSectionOffset()) { uint32_t pointer_size = 4; @@ -500,7 +501,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (symbol_name) { s->PutCString(symbol_name); - addr_t delta = file_Addr - symbol->GetAddress().GetFileAddress(); + addr_t delta = file_Addr - symbol->GetAddressRef().GetFileAddress(); if (delta) s->Printf(" + %" PRIu64, delta); showed_info = true; @@ -553,7 +554,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum #endif Address cstr_addr(*this); cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); - func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false, true); + func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false, true, true); if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr)) { #if VERBOSE_OUTPUT @@ -636,7 +637,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (pointer_sc.function || pointer_sc.symbol) { s->PutCString(": "); - pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false, true); + pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false, true, true); } } } @@ -662,12 +663,13 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum const bool show_fullpaths = false; const bool show_inlined_frames = true; const bool show_function_arguments = (style != DumpStyleResolvedDescriptionNoFunctionArguments); + const bool show_function_name = (style != DumpStyleNoFunctionName); if (sc.function == NULL && sc.symbol != NULL) { // If we have just a symbol make sure it is in the right section if (sc.symbol->ValueIsAddress()) { - if (sc.symbol->GetAddress().GetSection() != GetSection()) + if (sc.symbol->GetAddressRef().GetSection() != GetSection()) { // don't show the module if the symbol is a trampoline symbol show_stop_context = false; @@ -684,7 +686,8 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum show_fullpaths, show_module, show_inlined_frames, - show_function_arguments); + show_function_arguments, + show_function_name); } else { @@ -719,7 +722,7 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum // as our address. If it isn't, then we might have just found // the last symbol that came before the address that we are // looking up that has nothing to do with our address lookup. - if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddress().GetSection() != GetSection()) + if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddressRef().GetSection() != GetSection()) sc.symbol = NULL; } sc.GetDescription(s, eDescriptionLevelBrief, target); @@ -742,10 +745,15 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum if (var && var->LocationIsValidForAddress (*this)) { s->Indent(); - s->Printf (" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\", type= \"%s\", location =", + s->Printf (" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"", var->GetID(), - var->GetName().GetCString(), - var->GetType()->GetName().GetCString()); + var->GetName().GetCString()); + Type *type = var->GetType(); + if (type) + s->Printf(", type = \"%s\"", type->GetName().GetCString()); + else + s->PutCString(", type = "); + s->PutCString(", location = "); var->DumpLocationForAddress(s, *this); s->PutCString(", decl = "); var->GetDeclaration().DumpStopContext(s, false); diff --git a/source/Core/AddressResolver.cpp b/source/Core/AddressResolver.cpp index 5369d960f251..aa457015b4fd 100644 --- a/source/Core/AddressResolver.cpp +++ b/source/Core/AddressResolver.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/StreamString.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" -#include "lldb/lldb-private-log.h" using namespace lldb_private; diff --git a/source/Core/AddressResolverFileLine.cpp b/source/Core/AddressResolverFileLine.cpp index 6089abd76cbc..e45076e9bfc6 100644 --- a/source/Core/AddressResolverFileLine.cpp +++ b/source/Core/AddressResolverFileLine.cpp @@ -14,7 +14,6 @@ #include "lldb/Core/StreamString.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/SymbolContext.h" -#include "lldb/lldb-private-log.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp index 9f3b3f506fe0..1c6205fa6bdf 100644 --- a/source/Core/AddressResolverName.cpp +++ b/source/Core/AddressResolverName.cpp @@ -17,7 +17,6 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symbol.h" -#include "lldb/lldb-private-log.h" using namespace lldb; using namespace lldb_private; @@ -166,7 +165,7 @@ AddressResolverName::SearchCallback { if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) { - if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) + if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef()) { sym_list.RemoveContextAtIndex(j); continue; // Don't increment j @@ -212,7 +211,7 @@ AddressResolverName::SearchCallback { if (sc.symbol && sc.symbol->ValueIsAddress()) { - func_addr = sc.symbol->GetAddress(); + func_addr = sc.symbol->GetAddressRef(); addr_t byte_size = sc.symbol->GetByteSize(); if (skip_prologue) diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index 015f76bffbb5..33cbede9ce14 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -18,7 +18,7 @@ #include "llvm/Support/COFF.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Host.h" -#include "lldb/Utility/SafeMachO.h" + #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StringList.h" #include "lldb/Host/Endian.h" @@ -27,6 +27,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/NameMatches.h" +#include "lldb/Utility/SafeMachO.h" #include "Plugins/Process/Utility/ARMDefines.h" #include "Plugins/Process/Utility/InstructionUtils.h" @@ -87,7 +89,29 @@ static const CoreDefinition g_core_definitions[] = { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_armv8 , "armv8" }, { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_aarch64 , "aarch64" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" }, + // mips32, mips32r2, mips32r3, mips32r5, mips32r6 + { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32 , "mips" }, + { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r2 , "mipsr2" }, + { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r3 , "mipsr3" }, + { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r5 , "mipsr5" }, + { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r6 , "mipsr6" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32el , "mipsel" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r2el , "mipsr2el" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r3el , "mipsr3el" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r5el , "mipsr5el" }, + { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r6el , "mipsr6el" }, + + // mips64, mips64r2, mips64r3, mips64r5, mips64r6 + { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" }, + { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r2 , "mips64r2" }, + { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r3 , "mips64r3" }, + { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r5 , "mips64r5" }, + { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r6 , "mips64r6" }, + { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64el , "mips64el" }, + { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r2el , "mips64r2el" }, + { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r3el , "mips64r3el" }, + { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r5el , "mips64r5el" }, + { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r6el , "mips64r6el" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "powerpc" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc601 , "ppc601" }, @@ -259,14 +283,25 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { { ArchSpec::eCore_sparc_generic , llvm::ELF::EM_SPARC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Sparc { ArchSpec::eCore_x86_32_i386 , llvm::ELF::EM_386 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel 80386 - { ArchSpec::eCore_x86_32_i486 , llvm::ELF::EM_486 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel 486 (deprecated) + { ArchSpec::eCore_x86_32_i486 , llvm::ELF::EM_IAMCU , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel MCU // FIXME: is this correct? { ArchSpec::eCore_ppc_generic , llvm::ELF::EM_PPC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC { ArchSpec::eCore_ppc64_generic , llvm::ELF::EM_PPC64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC64 { ArchSpec::eCore_arm_generic , llvm::ELF::EM_ARM , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM { ArchSpec::eCore_arm_aarch64 , llvm::ELF::EM_AARCH64, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM64 { ArchSpec::eCore_sparc9_generic , llvm::ELF::EM_SPARCV9, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SPARC V9 { ArchSpec::eCore_x86_64_x86_64 , llvm::ELF::EM_X86_64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // AMD64 - { ArchSpec::eCore_mips64 , llvm::ELF::EM_MIPS , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // MIPS + { ArchSpec::eCore_mips32 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32 + { ArchSpec::eCore_mips32r2 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r2, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r2 + { ArchSpec::eCore_mips32r6 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r6, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r6 + { ArchSpec::eCore_mips32el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32el + { ArchSpec::eCore_mips32r2el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r2el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r2el + { ArchSpec::eCore_mips32r6el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r6el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r6el + { ArchSpec::eCore_mips64 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64 + { ArchSpec::eCore_mips64r2 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r2, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r2 + { ArchSpec::eCore_mips64r6 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r6, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r6 + { ArchSpec::eCore_mips64el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64el + { ArchSpec::eCore_mips64r2el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r2el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r2el + { ArchSpec::eCore_mips64r6el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r6el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r6el { ArchSpec::eCore_hexagon_generic , llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // HEXAGON { ArchSpec::eCore_kalimba3 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v3, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA { ArchSpec::eCore_kalimba4 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v4, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA @@ -573,6 +608,32 @@ ArchSpec::GetDefaultEndian () const return eByteOrderInvalid; } +bool +ArchSpec::CharIsSignedByDefault () const +{ + switch (m_triple.getArch()) { + default: + return true; + + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return m_triple.isOSDarwin() || m_triple.isOSWindows(); + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + return m_triple.isOSDarwin(); + + case llvm::Triple::ppc64le: + case llvm::Triple::systemz: + case llvm::Triple::xcore: + return false; + } +} + lldb::ByteOrder ArchSpec::GetByteOrder () const { @@ -779,7 +840,7 @@ ArchSpec::MergeFrom(const ArchSpec &other) } bool -ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t sub) +ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os) { m_core = kCore_invalid; bool update_triple = true; @@ -800,7 +861,6 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su if (arch_type == eArchTypeMachO) { m_triple.setVendor (llvm::Triple::Apple); - switch (core_def->machine) { case llvm::Triple::aarch64: @@ -825,10 +885,22 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su break; } } - else + else if (arch_type == eArchTypeELF) { + llvm::Triple::OSType ostype; + switch (os) + { + case llvm::ELF::ELFOSABI_AIX: ostype = llvm::Triple::OSType::AIX; break; + case llvm::ELF::ELFOSABI_FREEBSD: ostype = llvm::Triple::OSType::FreeBSD; break; + case llvm::ELF::ELFOSABI_GNU: ostype = llvm::Triple::OSType::Linux; break; + case llvm::ELF::ELFOSABI_NETBSD: ostype = llvm::Triple::OSType::NetBSD; break; + case llvm::ELF::ELFOSABI_OPENBSD: ostype = llvm::Triple::OSType::OpenBSD; break; + case llvm::ELF::ELFOSABI_SOLARIS: ostype = llvm::Triple::OSType::Solaris; break; + default: + ostype = llvm::Triple::OSType::UnknownOS; + } + m_triple.setOS (ostype); m_triple.setVendor (llvm::Triple::UnknownVendor); - m_triple.setOS (llvm::Triple::UnknownOS); } // Fall back onto setting the machine type if the arch by name failed... if (m_triple.getArch () == llvm::Triple::UnknownArch) @@ -1019,6 +1091,8 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in try_inverse = false; if (core2 == ArchSpec::eCore_arm_armv7) return true; + if (core2 == ArchSpec::eCore_arm_armv6m) + return true; } break; @@ -1027,8 +1101,36 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in return true; break; - case ArchSpec::eCore_arm_armv7m: case ArchSpec::eCore_arm_armv7em: + if (!enforce_exact_match) + { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + if (core2 == ArchSpec::eCore_arm_armv7m) + return true; + if (core2 == ArchSpec::eCore_arm_armv6m) + return true; + if (core2 == ArchSpec::eCore_arm_armv7) + return true; + try_inverse = true; + } + break; + + case ArchSpec::eCore_arm_armv7m: + if (!enforce_exact_match) + { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + if (core2 == ArchSpec::eCore_arm_armv6m) + return true; + if (core2 == ArchSpec::eCore_arm_armv7) + return true; + if (core2 == ArchSpec::eCore_arm_armv7em) + return true; + try_inverse = true; + } + break; + case ArchSpec::eCore_arm_armv7f: case ArchSpec::eCore_arm_armv7k: case ArchSpec::eCore_arm_armv7s: @@ -1084,6 +1186,36 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in } break; + case ArchSpec::eCore_mips64: + case ArchSpec::eCore_mips64r2: + case ArchSpec::eCore_mips64r3: + case ArchSpec::eCore_mips64r5: + case ArchSpec::eCore_mips64r6: + if (!enforce_exact_match) + { + if (core2 >= ArchSpec::kCore_mips32_first && core2 <= (core1 - 10)) + return true; + if (core2 >= ArchSpec::kCore_mips64_first && core2 <= (core1 - 1)) + return true; + try_inverse = false; + } + break; + + case ArchSpec::eCore_mips64el: + case ArchSpec::eCore_mips64r2el: + case ArchSpec::eCore_mips64r3el: + case ArchSpec::eCore_mips64r5el: + case ArchSpec::eCore_mips64r6el: + if (!enforce_exact_match) + { + if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= (core1 - 10)) + return true; + if (core2 >= ArchSpec::kCore_mips64el_first && core2 <= (core1 - 1)) + return true; + try_inverse = false; + } + break; + default: break; } diff --git a/source/Core/Broadcaster.cpp b/source/Core/Broadcaster.cpp index 1cbbde20e7f6..351487401f6b 100644 --- a/source/Core/Broadcaster.cpp +++ b/source/Core/Broadcaster.cpp @@ -16,7 +16,6 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Event.h" #include "lldb/Core/StreamString.h" -#include "lldb/lldb-private-log.h" using namespace lldb; using namespace lldb_private; diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp index ea84843fe0b3..ae579d1b00ae 100644 --- a/source/Core/Communication.cpp +++ b/source/Core/Communication.cpp @@ -11,7 +11,6 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-log.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Connection.h" #include "lldb/Core/Log.h" @@ -39,9 +38,11 @@ Communication::Communication(const char *name) : Broadcaster (NULL, name), m_connection_sp (), m_read_thread_enabled (false), + m_read_thread_did_exit (false), m_bytes(), m_bytes_mutex (Mutex::eMutexTypeRecursive), m_write_mutex (Mutex::eMutexTypeNormal), + m_synchronize_mutex (Mutex::eMutexTypeNormal), m_callback (NULL), m_callback_baton (NULL), m_close_on_eof (true) @@ -56,6 +57,7 @@ Communication::Communication(const char *name) : SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit"); SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit"); SetEventName (eBroadcastBitPacketAvailable, "packet available"); + SetEventName (eBroadcastBitNoMorePendingInput, "no more pending input"); CheckInWithManager(); } @@ -182,7 +184,8 @@ Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, Connectio if (event_type & eBroadcastBitReadThreadDidExit) { - Disconnect (NULL); + if (GetCloseOnEOF ()) + Disconnect (NULL); break; } } @@ -244,6 +247,7 @@ Communication::StartReadThread (Error *error_ptr) snprintf(thread_name, sizeof(thread_name), "", m_broadcaster_name.AsCString()); m_read_thread_enabled = true; + m_read_thread_did_exit = false; m_read_thread = ThreadLauncher::LaunchThread(thread_name, Communication::ReadThread, this, error_ptr); if (!m_read_thread.IsJoinable()) m_read_thread_enabled = false; @@ -376,9 +380,8 @@ Communication::ReadThread (lldb::thread_arg_t p) break; case eConnectionStatusEndOfFile: - if (comm->GetCloseOnEOF()) - done = true; - break; + done = true; + break; case eConnectionStatusError: // Check GetError() for details if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) { @@ -392,9 +395,13 @@ Communication::ReadThread (lldb::thread_arg_t p) p, Communication::ConnectionStatusAsCString (status)); break; + case eConnectionStatusInterrupted: // Synchronization signal from SynchronizeWithReadThread() + // The connection returns eConnectionStatusInterrupted only when there is no + // input pending to be read, so we can signal that. + comm->BroadcastEvent (eBroadcastBitNoMorePendingInput); + break; case eConnectionStatusNoConnection: // No connection case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection - case eConnectionStatusInterrupted: // Interrupted done = true; // Fall through... case eConnectionStatusTimedOut: // Request timed out @@ -410,7 +417,9 @@ Communication::ReadThread (lldb::thread_arg_t p) if (log) log->Printf ("%p Communication::ReadThread () thread exiting...", p); + comm->m_read_thread_did_exit = true; // Let clients know that this thread is exiting + comm->BroadcastEvent (eBroadcastBitNoMorePendingInput); comm->BroadcastEvent (eBroadcastBitReadThreadDidExit); return NULL; } @@ -426,6 +435,28 @@ Communication::SetReadThreadBytesReceivedCallback m_callback_baton = callback_baton; } +void +Communication::SynchronizeWithReadThread () +{ + // Only one thread can do the synchronization dance at a time. + Mutex::Locker locker(m_synchronize_mutex); + + // First start listening for the synchronization event. + Listener listener("Communication::SyncronizeWithReadThread"); + listener.StartListeningForEvents(this, eBroadcastBitNoMorePendingInput); + + // If the thread is not running, there is no point in synchronizing. + if (!m_read_thread_enabled || m_read_thread_did_exit) + return; + + // Notify the read thread. + m_connection_sp->InterruptRead(); + + // Wait for the synchronization event. + EventSP event_sp; + listener.WaitForEvent(NULL, event_sp); +} + void Communication::SetConnection (Connection *connection) { diff --git a/source/Core/ConnectionMachPort.cpp b/source/Core/ConnectionMachPort.cpp index fe29814be420..e04c48905570 100644 --- a/source/Core/ConnectionMachPort.cpp +++ b/source/Core/ConnectionMachPort.cpp @@ -17,7 +17,6 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private-log.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Log.h" @@ -69,7 +68,7 @@ ConnectionMachPort::Connect (const char *s, Error *error_ptr) ConnectionStatus status = eConnectionStatusError; - if (strncmp (s, "bootstrap-checkin://", strlen("bootstrap-checkin://"))) + if (0 == strncmp (s, "bootstrap-checkin://", strlen("bootstrap-checkin://"))) { s += strlen("bootstrap-checkin://"); @@ -83,7 +82,7 @@ ConnectionMachPort::Connect (const char *s, Error *error_ptr) error_ptr->SetErrorString ("bootstrap port name is empty"); } } - else if (strncmp (s, "bootstrap-lookup://", strlen("bootstrap-lookup://"))) + else if (0 == strncmp (s, "bootstrap-lookup://", strlen("bootstrap-lookup://"))) { s += strlen("bootstrap-lookup://"); if (*s) diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp index d3dfa3cd8d56..77daeb14840d 100644 --- a/source/Core/ConnectionSharedMemory.cpp +++ b/source/Core/ConnectionSharedMemory.cpp @@ -26,7 +26,6 @@ // Other libraries and framework includes // Project includes #include "llvm/Support/MathExtras.h" -#include "lldb/lldb-private-log.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Log.h" diff --git a/source/Core/CxaDemangle.cpp b/source/Core/CxaDemangle.cpp new file mode 100644 index 000000000000..bcc52ff39fe4 --- /dev/null +++ b/source/Core/CxaDemangle.cpp @@ -0,0 +1,5011 @@ +//---------------------------------------------------------------------- +// Inlined copy of: +// http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp +// revision 238263. +// +// Changes include: +// - Renamed the "__cxxabiv1" namespace to "lldb_private" +// - Stripped GCC attributes() +// - Removed extern "C" from the cxa_demangle function +// - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning +// - Implemented missing rebind, construct, destroy in malloc_alloc +// - Replaced noexcept, constexpr, alignas with their LLVM_* equivalents +// - Included win32.h for snprintf implementation for MSVC +// - Removed constexpr member initialization for MSVC +// - Changed argument to alignas() to a literal for MSVC +//---------------------------------------------------------------------- + +#if defined(_MSC_VER) +#include "lldb/Host/windows/win32.h" // snprintf +#endif +#include "llvm/Support/Compiler.h" // LLVM_{NOEXCEPT, CONSTEXPR, ALIGNAS} +#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below + +//===-------------------------- cxa_demangle.cpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define _LIBCPP_EXTERN_TEMPLATE(...) +#define _LIBCPP_NO_EXCEPTIONS + +#include +#include +#include +#include +#include +#include +#include + +namespace lldb_private +{ + +namespace +{ + +enum +{ + unknown_error = -4, + invalid_args = -3, + invalid_mangled_name, + memory_alloc_failure, + success +}; + +template + const char* parse_type(const char* first, const char* last, C& db); +template + const char* parse_encoding(const char* first, const char* last, C& db); +template + const char* parse_name(const char* first, const char* last, C& db, + bool* ends_with_template_args = 0); +template + const char* parse_expression(const char* first, const char* last, C& db); +template + const char* parse_template_args(const char* first, const char* last, C& db); +template + const char* parse_operator_name(const char* first, const char* last, C& db); +template + const char* parse_unqualified_name(const char* first, const char* last, C& db); +template + const char* parse_decltype(const char* first, const char* last, C& db); + +template +void +print_stack(const C& db) +{ + fprintf(stderr, "---------\n"); + fprintf(stderr, "names:\n"); + for (auto& s : db.names) + fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str()); + int i = -1; + fprintf(stderr, "subs:\n"); + for (auto& v : db.subs) + { + if (i >= 0) + fprintf(stderr, "S%i_ = {", i); + else + fprintf(stderr, "S_ = {"); + for (auto& s : v) + fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "}\n"); + ++i; + } + fprintf(stderr, "template_param:\n"); + for (auto& t : db.template_param) + { + fprintf(stderr, "--\n"); + i = -1; + for (auto& v : t) + { + if (i >= 0) + fprintf(stderr, "T%i_ = {", i); + else + fprintf(stderr, "T_ = {"); + for (auto& s : v) + fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "}\n"); + ++i; + } + } + fprintf(stderr, "---------\n\n"); +} + +template +void +print_state(const char* msg, const char* first, const char* last, const C& db) +{ + fprintf(stderr, "%s: ", msg); + for (; first != last; ++first) + fprintf(stderr, "%c", *first); + fprintf(stderr, "\n"); + print_stack(db); +} + +// ::= [n] + +const char* +parse_number(const char* first, const char* last) +{ + if (first != last) + { + const char* t = first; + if (*t == 'n') + ++t; + if (t != last) + { + if (*t == '0') + { + first = t+1; + } + else if ('1' <= *t && *t <= '9') + { + first = t+1; + while (first != last && std::isdigit(*first)) + ++first; + } + } + } + return first; +} + +template +struct float_data; + +template <> +struct float_data +{ + static const size_t mangled_size = 8; + static const size_t max_demangled_size = 24; + static const char* spec; +}; + +const char* float_data::spec = "%af"; + +template <> +struct float_data +{ + static const size_t mangled_size = 16; + static const size_t max_demangled_size = 32; + static const char* spec; +}; + +const char* float_data::spec = "%a"; + +template <> +struct float_data +{ +#if defined(__arm__) + static const size_t mangled_size = 16; +#else + static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms +#endif + static const size_t max_demangled_size = 40; + static const char* spec; +}; + +const char* float_data::spec = "%LaL"; + +template +const char* +parse_floating_number(const char* first, const char* last, C& db) +{ + const size_t N = float_data::mangled_size; + if (static_cast(last - first) > N) + { + last = first + N; + union + { + Float value; + char buf[sizeof(Float)]; + }; + const char* t = first; + char* e = buf; + for (; t != last; ++t, ++e) + { + if (!isxdigit(*t)) + return first; + unsigned d1 = isdigit(*t) ? static_cast(*t - '0') : + static_cast(*t - 'a' + 10); + ++t; + unsigned d0 = isdigit(*t) ? static_cast(*t - '0') : + static_cast(*t - 'a' + 10); + *e = static_cast((d1 << 4) + d0); + } + if (*t == 'E') + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::reverse(buf, e); +#endif + char num[float_data::max_demangled_size] = {0}; + int n = snprintf(num, sizeof(num), float_data::spec, value); + if (static_cast(n) >= sizeof(num)) + return first; + db.names.push_back(typename C::String(num, static_cast(n))); + first = t+1; + } + } + return first; +} + +// ::= + +template +const char* +parse_source_name(const char* first, const char* last, C& db) +{ + if (first != last) + { + char c = *first; + if (isdigit(c) && first+1 != last) + { + const char* t = first+1; + size_t n = static_cast(c - '0'); + for (c = *t; isdigit(c); c = *t) + { + n = n * 10 + static_cast(c - '0'); + if (++t == last) + return first; + } + if (static_cast(last - t) >= n) + { + typename C::String r(t, n); + if (r.substr(0, 10) == "_GLOBAL__N") + db.names.push_back("(anonymous namespace)"); + else + db.names.push_back(std::move(r)); + first = t + n; + } + } + } + return first; +} + +// ::= S _ +// ::= S_ +// ::= Sa # ::std::allocator +// ::= Sb # ::std::basic_string +// ::= Ss # ::std::basic_string < char, +// ::std::char_traits, +// ::std::allocator > +// ::= Si # ::std::basic_istream > +// ::= So # ::std::basic_ostream > +// ::= Sd # ::std::basic_iostream > + +template +const char* +parse_substitution(const char* first, const char* last, C& db) +{ + if (last - first >= 2) + { + if (*first == 'S') + { + switch (first[1]) + { + case 'a': + db.names.push_back("std::allocator"); + first += 2; + break; + case 'b': + db.names.push_back("std::basic_string"); + first += 2; + break; + case 's': + db.names.push_back("std::string"); + first += 2; + break; + case 'i': + db.names.push_back("std::istream"); + first += 2; + break; + case 'o': + db.names.push_back("std::ostream"); + first += 2; + break; + case 'd': + db.names.push_back("std::iostream"); + first += 2; + break; + case '_': + if (!db.subs.empty()) + { + for (const auto& n : db.subs.front()) + db.names.push_back(n); + first += 2; + } + break; + default: + if (std::isdigit(first[1]) || std::isupper(first[1])) + { + size_t sub = 0; + const char* t = first+1; + if (std::isdigit(*t)) + sub = static_cast(*t - '0'); + else + sub = static_cast(*t - 'A') + 10; + for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t) + { + sub *= 36; + if (std::isdigit(*t)) + sub += static_cast(*t - '0'); + else + sub += static_cast(*t - 'A') + 10; + } + if (t == last || *t != '_') + return first; + ++sub; + if (sub < db.subs.size()) + { + for (const auto& n : db.subs[sub]) + db.names.push_back(n); + first = t+1; + } + } + break; + } + } + } + return first; +} + +// ::= v # void +// ::= w # wchar_t +// ::= b # bool +// ::= c # char +// ::= a # signed char +// ::= h # unsigned char +// ::= s # short +// ::= t # unsigned short +// ::= i # int +// ::= j # unsigned int +// ::= l # long +// ::= m # unsigned long +// ::= x # long long, __int64 +// ::= y # unsigned long long, __int64 +// ::= n # __int128 +// ::= o # unsigned __int128 +// ::= f # float +// ::= d # double +// ::= e # long double, __float80 +// ::= g # __float128 +// ::= z # ellipsis +// ::= Dd # IEEE 754r decimal floating point (64 bits) +// ::= De # IEEE 754r decimal floating point (128 bits) +// ::= Df # IEEE 754r decimal floating point (32 bits) +// ::= Dh # IEEE 754r half-precision floating point (16 bits) +// ::= Di # char32_t +// ::= Ds # char16_t +// ::= Da # auto (in dependent new-expressions) +// ::= Dc # decltype(auto) +// ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) +// ::= u # vendor extended type + +template +const char* +parse_builtin_type(const char* first, const char* last, C& db) +{ + if (first != last) + { + switch (*first) + { + case 'v': + db.names.push_back("void"); + ++first; + break; + case 'w': + db.names.push_back("wchar_t"); + ++first; + break; + case 'b': + db.names.push_back("bool"); + ++first; + break; + case 'c': + db.names.push_back("char"); + ++first; + break; + case 'a': + db.names.push_back("signed char"); + ++first; + break; + case 'h': + db.names.push_back("unsigned char"); + ++first; + break; + case 's': + db.names.push_back("short"); + ++first; + break; + case 't': + db.names.push_back("unsigned short"); + ++first; + break; + case 'i': + db.names.push_back("int"); + ++first; + break; + case 'j': + db.names.push_back("unsigned int"); + ++first; + break; + case 'l': + db.names.push_back("long"); + ++first; + break; + case 'm': + db.names.push_back("unsigned long"); + ++first; + break; + case 'x': + db.names.push_back("long long"); + ++first; + break; + case 'y': + db.names.push_back("unsigned long long"); + ++first; + break; + case 'n': + db.names.push_back("__int128"); + ++first; + break; + case 'o': + db.names.push_back("unsigned __int128"); + ++first; + break; + case 'f': + db.names.push_back("float"); + ++first; + break; + case 'd': + db.names.push_back("double"); + ++first; + break; + case 'e': + db.names.push_back("long double"); + ++first; + break; + case 'g': + db.names.push_back("__float128"); + ++first; + break; + case 'z': + db.names.push_back("..."); + ++first; + break; + case 'u': + { + const char*t = parse_source_name(first+1, last, db); + if (t != first+1) + first = t; + } + break; + case 'D': + if (first+1 != last) + { + switch (first[1]) + { + case 'd': + db.names.push_back("decimal64"); + first += 2; + break; + case 'e': + db.names.push_back("decimal128"); + first += 2; + break; + case 'f': + db.names.push_back("decimal32"); + first += 2; + break; + case 'h': + db.names.push_back("decimal16"); + first += 2; + break; + case 'i': + db.names.push_back("char32_t"); + first += 2; + break; + case 's': + db.names.push_back("char16_t"); + first += 2; + break; + case 'a': + db.names.push_back("auto"); + first += 2; + break; + case 'c': + db.names.push_back("decltype(auto)"); + first += 2; + break; + case 'n': + db.names.push_back("std::nullptr_t"); + first += 2; + break; + } + } + break; + } + } + return first; +} + +// ::= [r] [V] [K] + +const char* +parse_cv_qualifiers(const char* first, const char* last, unsigned& cv) +{ + cv = 0; + if (first != last) + { + if (*first == 'r') + { + cv |= 4; + ++first; + } + if (*first == 'V') + { + cv |= 2; + ++first; + } + if (*first == 'K') + { + cv |= 1; + ++first; + } + } + return first; +} + +// ::= T_ # first template parameter +// ::= T _ + +template +const char* +parse_template_param(const char* first, const char* last, C& db) +{ + if (last - first >= 2) + { + if (*first == 'T') + { + if (first[1] == '_') + { + if (db.template_param.empty()) + return first; + if (!db.template_param.back().empty()) + { + for (auto& t : db.template_param.back().front()) + db.names.push_back(t); + first += 2; + } + else + { + db.names.push_back("T_"); + first += 2; + db.fix_forward_references = true; + } + } + else if (isdigit(first[1])) + { + const char* t = first+1; + size_t sub = static_cast(*t - '0'); + for (++t; t != last && isdigit(*t); ++t) + { + sub *= 10; + sub += static_cast(*t - '0'); + } + if (t == last || *t != '_' || db.template_param.empty()) + return first; + ++sub; + if (sub < db.template_param.back().size()) + { + for (auto& temp : db.template_param.back()[sub]) + db.names.push_back(temp); + first = t+1; + } + else + { + db.names.push_back(typename C::String(first, t+1)); + first = t+1; + db.fix_forward_references = true; + } + } + } + } + return first; +} + +// cc # const_cast (expression) + +template +const char* +parse_const_cast_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'c' && first[1] == 'c') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_expression(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } + } + } + return first; +} + +// dc # dynamic_cast (expression) + +template +const char* +parse_dynamic_cast_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'd' && first[1] == 'c') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_expression(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } + } + } + return first; +} + +// rc # reinterpret_cast (expression) + +template +const char* +parse_reinterpret_cast_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'r' && first[1] == 'c') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_expression(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } + } + } + return first; +} + +// sc # static_cast (expression) + +template +const char* +parse_static_cast_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 's' && first[1] == 'c') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_expression(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } + } + } + return first; +} + +// sp # pack expansion + +template +const char* +parse_pack_expansion(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 's' && first[1] == 'p') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + first = t; + } + return first; +} + +// st # sizeof (a type) + +template +const char* +parse_sizeof_type_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 's' && first[1] == 't') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; + first = t; + } + } + return first; +} + +// sz # sizeof (a expression) + +template +const char* +parse_sizeof_expr_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 's' && first[1] == 'z') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; + first = t; + } + } + return first; +} + +// sZ # size of a parameter pack + +template +const char* +parse_sizeof_param_pack_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'T') + { + size_t k0 = db.names.size(); + const char* t = parse_template_param(first+2, last, db); + size_t k1 = db.names.size(); + if (t != first+2) + { + typename C::String tmp("sizeof...("); + size_t k = k0; + if (k != k1) + { + tmp += db.names[k].move_full(); + for (++k; k != k1; ++k) + tmp += ", " + db.names[k].move_full(); + } + tmp += ")"; + for (; k1 != k0; --k1) + db.names.pop_back(); + db.names.push_back(std::move(tmp)); + first = t; + } + } + return first; +} + +// ::= fp _ # L == 0, first parameter +// ::= fp _ # L == 0, second and later parameters +// ::= fL p _ # L > 0, first parameter +// ::= fL p _ # L > 0, second and later parameters + +template +const char* +parse_function_param(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && *first == 'f') + { + if (first[1] == 'p') + { + unsigned cv; + const char* t = parse_cv_qualifiers(first+2, last, cv); + const char* t1 = parse_number(t, last); + if (t1 != last && *t1 == '_') + { + db.names.push_back("fp" + typename C::String(t, t1)); + first = t1+1; + } + } + else if (first[1] == 'L') + { + unsigned cv; + const char* t0 = parse_number(first+2, last); + if (t0 != last && *t0 == 'p') + { + ++t0; + const char* t = parse_cv_qualifiers(t0, last, cv); + const char* t1 = parse_number(t, last); + if (t1 != last && *t1 == '_') + { + db.names.push_back("fp" + typename C::String(t, t1)); + first = t1+1; + } + } + } + } + return first; +} + +// sZ # size of a function parameter pack + +template +const char* +parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'f') + { + const char* t = parse_function_param(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "sizeof...(" + db.names.back().move_full() + ")"; + first = t; + } + } + return first; +} + +// te # typeid (expression) +// ti # typeid (type) + +template +const char* +parse_typeid_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 't' && (first[1] == 'e' || first[1] == 'i')) + { + const char* t; + if (first[1] == 'e') + t = parse_expression(first+2, last, db); + else + t = parse_type(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "typeid(" + db.names.back().move_full() + ")"; + first = t; + } + } + return first; +} + +// tw # throw expression + +template +const char* +parse_throw_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 't' && first[1] == 'w') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "throw " + db.names.back().move_full(); + first = t; + } + } + return first; +} + +// ds # expr.*expr + +template +const char* +parse_dot_star_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'd' && first[1] == 's') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_expression(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += ".*" + expr; + first = t1; + } + } + } + return first; +} + +// ::= [ ] + +template +const char* +parse_simple_id(const char* first, const char* last, C& db) +{ + if (first != last) + { + const char* t = parse_source_name(first, last, db); + if (t != first) + { + const char* t1 = parse_template_args(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + } + first = t1; + } + else + first = t; + } + return first; +} + +// ::= +// ::= +// ::= + +template +const char* +parse_unresolved_type(const char* first, const char* last, C& db) +{ + if (first != last) + { + const char* t = first; + switch (*first) + { + case 'T': + { + size_t k0 = db.names.size(); + t = parse_template_param(first, last, db); + size_t k1 = db.names.size(); + if (t != first && k1 == k0 + 1) + { + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + else + { + for (; k1 != k0; --k1) + db.names.pop_back(); + } + break; + } + case 'D': + t = parse_decltype(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + break; + case 'S': + t = parse_substitution(first, last, db); + if (t != first) + first = t; + else + { + if (last - first > 2 && first[1] == 't') + { + t = parse_unqualified_name(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "std::"); + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + } + } + break; + } + } + return first; +} + +// ::= # e.g., ~T or ~decltype(f()) +// ::= # e.g., ~A<2*N> + +template +const char* +parse_destructor_name(const char* first, const char* last, C& db) +{ + if (first != last) + { + const char* t = parse_unresolved_type(first, last, db); + if (t == first) + t = parse_simple_id(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "~"); + first = t; + } + } + return first; +} + +// ::= # unresolved name +// extension ::= # unresolved operator-function-id +// extension ::= # unresolved operator template-id +// ::= on # unresolved operator-function-id +// ::= on # unresolved operator template-id +// ::= dn # destructor or pseudo-destructor; +// # e.g. ~X or ~X + +template +const char* +parse_base_unresolved_name(const char* first, const char* last, C& db) +{ + if (last - first >= 2) + { + if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n') + { + if (first[0] == 'o') + { + const char* t = parse_operator_name(first+2, last, db); + if (t != first+2) + { + first = parse_template_args(t, last, db); + if (first != t) + { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + } + } + } + else + { + const char* t = parse_destructor_name(first+2, last, db); + if (t != first+2) + first = t; + } + } + else + { + const char* t = parse_simple_id(first, last, db); + if (t == first) + { + t = parse_operator_name(first, last, db); + if (t != first) + { + first = parse_template_args(t, last, db); + if (first != t) + { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + } + } + } + else + first = t; + } + } + return first; +} + +// ::= + +template +const char* +parse_unresolved_qualifier_level(const char* first, const char* last, C& db) +{ + return parse_simple_id(first, last, db); +} + +// +// extension ::= srN [] * E +// ::= [gs] # x or (with "gs") ::x +// ::= [gs] sr + E +// # A::x, N::y, A::z; "gs" means leading "::" +// ::= sr # T::x / decltype(p)::x +// extension ::= sr +// # T::N::x /decltype(p)::N::x +// (ignored) ::= srN + E + +template +const char* +parse_unresolved_name(const char* first, const char* last, C& db) +{ + if (last - first > 2) + { + const char* t = first; + bool global = false; + if (t[0] == 'g' && t[1] == 's') + { + global = true; + t += 2; + } + const char* t2 = parse_base_unresolved_name(t, last, db); + if (t2 != t) + { + if (global) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "::"); + } + first = t2; + } + else if (last - t > 2 && t[0] == 's' && t[1] == 'r') + { + if (t[2] == 'N') + { + t += 3; + const char* t1 = parse_unresolved_type(t, last, db); + if (t1 == t || t1 == last) + return first; + t = t1; + t1 = parse_template_args(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + t = t1; + if (t == last) + { + db.names.pop_back(); + return first; + } + } + while (*t != 'E') + { + t1 = parse_unresolved_qualifier_level(t, last, db); + if (t1 == t || t1 == last || db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + t = t1; + } + ++t; + t1 = parse_base_unresolved_name(t, last, db); + if (t1 == t) + { + if (!db.names.empty()) + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + first = t1; + } + else + { + t += 2; + const char* t1 = parse_unresolved_type(t, last, db); + if (t1 != t) + { + t = t1; + t1 = parse_template_args(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + t = t1; + } + t1 = parse_base_unresolved_name(t, last, db); + if (t1 == t) + { + if (!db.names.empty()) + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + first = t1; + } + else + { + t1 = parse_unresolved_qualifier_level(t, last, db); + if (t1 == t || t1 == last) + return first; + t = t1; + if (global) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "::"); + } + while (*t != 'E') + { + t1 = parse_unresolved_qualifier_level(t, last, db); + if (t1 == t || t1 == last || db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + t = t1; + } + ++t; + t1 = parse_base_unresolved_name(t, last, db); + if (t1 == t) + { + if (!db.names.empty()) + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + first = t1; + } + } + } + } + return first; +} + +// dt # expr.name + +template +const char* +parse_dot_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'd' && first[1] == 't') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_unresolved_name(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto name = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "." + name; + first = t1; + } + } + } + return first; +} + +// cl + E # call + +template +const char* +parse_call_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 4 && first[0] == 'c' && first[1] == 'l') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + if (t == last) + return first; + if (db.names.empty()) + return first; + db.names.back().first += db.names.back().second; + db.names.back().second = typename C::String(); + db.names.back().first.append("("); + bool first_expr = true; + while (*t != 'E') + { + const char* t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + if (db.names.empty()) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) + { + if (db.names.empty()) + return first; + if (!first_expr) + { + db.names.back().first.append(", "); + first_expr = false; + } + db.names.back().first.append(tmp); + } + t = t1; + } + ++t; + if (db.names.empty()) + return first; + db.names.back().first.append(")"); + first = t; + } + } + return first; +} + +// [gs] nw * _ E # new (expr-list) type +// [gs] nw * _ # new (expr-list) type (init) +// [gs] na * _ E # new[] (expr-list) type +// [gs] na * _ # new[] (expr-list) type (init) +// ::= pi * E # parenthesized initialization + +template +const char* +parse_new_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 4) + { + const char* t = first; + bool parsed_gs = false; + if (t[0] == 'g' && t[1] == 's') + { + t += 2; + parsed_gs = true; + } + if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a')) + { + bool is_array = t[1] == 'a'; + t += 2; + if (t == last) + return first; + bool has_expr_list = false; + bool first_expr = true; + while (*t != '_') + { + const char* t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + has_expr_list = true; + if (!first_expr) + { + if (db.names.empty()) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) + { + if (db.names.empty()) + return first; + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + first_expr = false; + } + } + t = t1; + } + ++t; + const char* t1 = parse_type(t, last, db); + if (t1 == t || t1 == last) + return first; + t = t1; + bool has_init = false; + if (last - t >= 3 && t[0] == 'p' && t[1] == 'i') + { + t += 2; + has_init = true; + first_expr = true; + while (*t != 'E') + { + t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + if (!first_expr) + { + if (db.names.empty()) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) + { + if (db.names.empty()) + return first; + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + first_expr = false; + } + } + t = t1; + } + } + if (*t != 'E') + return first; + typename C::String init_list; + if (has_init) + { + if (db.names.empty()) + return first; + init_list = db.names.back().move_full(); + db.names.pop_back(); + } + if (db.names.empty()) + return first; + auto type = db.names.back().move_full(); + db.names.pop_back(); + typename C::String expr_list; + if (has_expr_list) + { + if (db.names.empty()) + return first; + expr_list = db.names.back().move_full(); + db.names.pop_back(); + } + typename C::String r; + if (parsed_gs) + r = "::"; + if (is_array) + r += "[] "; + else + r += " "; + if (has_expr_list) + r += "(" + expr_list + ") "; + r += type; + if (has_init) + r += " (" + init_list + ")"; + db.names.push_back(std::move(r)); + first = t+1; + } + } + return first; +} + +// cv # conversion with one argument +// cv _ * E # conversion with a different number of arguments + +template +const char* +parse_conversion_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'c' && first[1] == 'v') + { + bool try_to_parse_template_args = db.try_to_parse_template_args; + db.try_to_parse_template_args = false; + const char* t = parse_type(first+2, last, db); + db.try_to_parse_template_args = try_to_parse_template_args; + if (t != first+2 && t != last) + { + if (*t != '_') + { + const char* t1 = parse_expression(t, last, db); + if (t1 == t) + return first; + t = t1; + } + else + { + ++t; + if (t == last) + return first; + if (*t == 'E') + db.names.emplace_back(); + else + { + bool first_expr = true; + while (*t != 'E') + { + const char* t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + if (!first_expr) + { + if (db.names.empty()) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) + { + if (db.names.empty()) + return first; + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + first_expr = false; + } + } + t = t1; + } + } + ++t; + } + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")"; + first = t; + } + } + return first; +} + +// pt # expr->name + +template +const char* +parse_arrow_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'p' && first[1] == 't') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + const char* t1 = parse_expression(t, last, db); + if (t1 != t) + { + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "->"; + db.names.back().first += tmp; + first = t1; + } + } + } + return first; +} + +// ::= R # & ref-qualifier +// ::= O # && ref-qualifier + +// ::= F [Y] [] E + +template +const char* +parse_function_type(const char* first, const char* last, C& db) +{ + if (first != last && *first == 'F') + { + const char* t = first+1; + if (t != last) + { + if (*t == 'Y') + { + /* extern "C" */ + if (++t == last) + return first; + } + const char* t1 = parse_type(t, last, db); + if (t1 != t) + { + t = t1; + typename C::String sig("("); + int ref_qual = 0; + while (true) + { + if (t == last) + { + db.names.pop_back(); + return first; + } + if (*t == 'E') + { + ++t; + break; + } + if (*t == 'v') + { + ++t; + continue; + } + if (*t == 'R' && t+1 != last && t[1] == 'E') + { + ref_qual = 1; + ++t; + continue; + } + if (*t == 'O' && t+1 != last && t[1] == 'E') + { + ref_qual = 2; + ++t; + continue; + } + size_t k0 = db.names.size(); + t1 = parse_type(t, last, db); + size_t k1 = db.names.size(); + if (t1 == t || t1 == last) + return first; + for (size_t k = k0; k < k1; ++k) + { + if (sig.size() > 1) + sig += ", "; + sig += db.names[k].move_full(); + } + for (size_t k = k0; k < k1; ++k) + db.names.pop_back(); + t = t1; + } + sig += ")"; + switch (ref_qual) + { + case 1: + sig += " &"; + break; + case 2: + sig += " &&"; + break; + } + if (db.names.empty()) + return first; + db.names.back().first += " "; + db.names.back().second.insert(0, sig); + first = t; + } + } + } + return first; +} + +// ::= M + +template +const char* +parse_pointer_to_member_type(const char* first, const char* last, C& db) +{ + if (first != last && *first == 'M') + { + const char* t = parse_type(first+1, last, db); + if (t != first+1) + { + const char* t2 = parse_type(t, last, db); + if (t2 != t) + { + if (db.names.size() < 2) + return first; + auto func = std::move(db.names.back()); + db.names.pop_back(); + auto class_type = std::move(db.names.back()); + if (!func.second.empty() && func.second.front() == '(') + { + db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*"; + db.names.back().second = ")" + std::move(func.second); + } + else + { + db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*"; + db.names.back().second = std::move(func.second); + } + first = t2; + } + } + } + return first; +} + +// ::= A _ +// ::= A [] _ + +template +const char* +parse_array_type(const char* first, const char* last, C& db) +{ + if (first != last && *first == 'A' && first+1 != last) + { + if (first[1] == '_') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + if (db.names.back().second.substr(0, 2) == " [") + db.names.back().second.erase(0, 1); + db.names.back().second.insert(0, " []"); + first = t; + } + } + else if ('1' <= first[1] && first[1] <= '9') + { + const char* t = parse_number(first+1, last); + if (t != last && *t == '_') + { + const char* t2 = parse_type(t+1, last, db); + if (t2 != t+1) + { + if (db.names.empty()) + return first; + if (db.names.back().second.substr(0, 2) == " [") + db.names.back().second.erase(0, 1); + db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]"); + first = t2; + } + } + } + else + { + const char* t = parse_expression(first+1, last, db); + if (t != first+1 && t != last && *t == '_') + { + const char* t2 = parse_type(++t, last, db); + if (t2 != t) + { + if (db.names.size() < 2) + return first; + auto type = std::move(db.names.back()); + db.names.pop_back(); + auto expr = std::move(db.names.back()); + db.names.back().first = std::move(type.first); + if (type.second.substr(0, 2) == " [") + type.second.erase(0, 1); + db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second); + first = t2; + } + } + } + } + return first; +} + +// ::= Dt E # decltype of an id-expression or class member access (C++0x) +// ::= DT E # decltype of an expression (C++0x) + +template +const char* +parse_decltype(const char* first, const char* last, C& db) +{ + if (last - first >= 4 && first[0] == 'D') + { + switch (first[1]) + { + case 't': + case 'T': + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2 && t != last && *t == 'E') + { + if (db.names.empty()) + return first; + db.names.back() = "decltype(" + db.names.back().move_full() + ")"; + first = t+1; + } + } + break; + } + } + return first; +} + +// extension: +// ::= Dv _ +// +// ::= Dv [] _ +// ::= +// ::= p # AltiVec vector pixel + +template +const char* +parse_vector_type(const char* first, const char* last, C& db) +{ + if (last - first > 3 && first[0] == 'D' && first[1] == 'v') + { + if ('1' <= first[2] && first[2] <= '9') + { + const char* t = parse_number(first+2, last); + if (t == last || *t != '_') + return first; + const char* num = first + 2; + size_t sz = static_cast(t - num); + if (++t != last) + { + if (*t != 'p') + { + const char* t1 = parse_type(t, last, db); + if (t1 != t) + { + if (db.names.empty()) + return first; + db.names.back().first += " vector[" + typename C::String(num, sz) + "]"; + first = t1; + } + } + else + { + ++t; + db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]"); + first = t; + } + } + } + else + { + typename C::String num; + const char* t1 = first+2; + if (*t1 != '_') + { + const char* t = parse_expression(t1, last, db); + if (t != t1) + { + if (db.names.empty()) + return first; + num = db.names.back().move_full(); + db.names.pop_back(); + t1 = t; + } + } + if (t1 != last && *t1 == '_' && ++t1 != last) + { + const char* t = parse_type(t1, last, db); + if (t != t1) + { + if (db.names.empty()) + return first; + db.names.back().first += " vector[" + num + "]"; + first = t; + } + } + } + } + return first; +} + +// ::= +// ::= +// ::= +// ::= +// ::= +// ::= +// ::= +// ::= +// ::= +// ::= +// ::= P # pointer-to +// ::= R # reference-to +// ::= O # rvalue reference-to (C++0x) +// ::= C # complex pair (C 2000) +// ::= G # imaginary (C 2000) +// ::= Dp # pack expansion (C++0x) +// ::= U # vendor extended type qualifier +// extension := U # objc-type +// extension := # starts with Dv + +// ::= objcproto # k0 = 9 + + k1 +// := # PU<11+>objcproto 11objc_object 11objc_object -> id + +template +const char* +parse_type(const char* first, const char* last, C& db) +{ + if (first != last) + { + switch (*first) + { + case 'r': + case 'V': + case 'K': + { + unsigned cv = 0; + const char* t = parse_cv_qualifiers(first, last, cv); + if (t != first) + { + bool is_function = *t == 'F'; + size_t k0 = db.names.size(); + const char* t1 = parse_type(t, last, db); + size_t k1 = db.names.size(); + if (t1 != t) + { + if (is_function) + db.subs.pop_back(); + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + { + if (is_function) + { + size_t p = db.names[k].second.size(); + if (db.names[k].second[p-2] == '&') + p -= 3; + else if (db.names[k].second.back() == '&') + p -= 2; + if (cv & 1) + { + db.names[k].second.insert(p, " const"); + p += 6; + } + if (cv & 2) + { + db.names[k].second.insert(p, " volatile"); + p += 9; + } + if (cv & 4) + db.names[k].second.insert(p, " restrict"); + } + else + { + if (cv & 1) + db.names[k].first.append(" const"); + if (cv & 2) + db.names[k].first.append(" volatile"); + if (cv & 4) + db.names[k].first.append(" restrict"); + } + db.subs.back().push_back(db.names[k]); + } + first = t1; + } + } + } + break; + default: + { + const char* t = parse_builtin_type(first, last, db); + if (t != first) + { + first = t; + } + else + { + switch (*first) + { + case 'A': + t = parse_array_type(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + } + break; + case 'C': + t = parse_type(first+1, last, db); + if (t != first+1) + { + if (db.names.empty()) + return first; + db.names.back().first.append(" complex"); + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + } + break; + case 'F': + t = parse_function_type(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + } + break; + case 'G': + t = parse_type(first+1, last, db); + if (t != first+1) + { + if (db.names.empty()) + return first; + db.names.back().first.append(" imaginary"); + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + } + break; + case 'M': + t = parse_pointer_to_member_type(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + } + break; + case 'O': + { + size_t k0 = db.names.size(); + t = parse_type(first+1, last, db); + size_t k1 = db.names.size(); + if (t != first+1) + { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + { + if (db.names[k].second.substr(0, 2) == " [") + { + db.names[k].first += " ("; + db.names[k].second.insert(0, ")"); + } + else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') + { + db.names[k].first += "("; + db.names[k].second.insert(0, ")"); + } + db.names[k].first.append("&&"); + db.subs.back().push_back(db.names[k]); + } + first = t; + } + break; + } + case 'P': + { + size_t k0 = db.names.size(); + t = parse_type(first+1, last, db); + size_t k1 = db.names.size(); + if (t != first+1) + { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + { + if (db.names[k].second.substr(0, 2) == " [") + { + db.names[k].first += " ("; + db.names[k].second.insert(0, ")"); + } + else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') + { + db.names[k].first += "("; + db.names[k].second.insert(0, ")"); + } + if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<") + { + db.names[k].first.append("*"); + } + else + { + db.names[k].first.replace(0, 11, "id"); + } + db.subs.back().push_back(db.names[k]); + } + first = t; + } + break; + } + case 'R': + { + size_t k0 = db.names.size(); + t = parse_type(first+1, last, db); + size_t k1 = db.names.size(); + if (t != first+1) + { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + { + if (db.names[k].second.substr(0, 2) == " [") + { + db.names[k].first += " ("; + db.names[k].second.insert(0, ")"); + } + else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') + { + db.names[k].first += "("; + db.names[k].second.insert(0, ")"); + } + db.names[k].first.append("&"); + db.subs.back().push_back(db.names[k]); + } + first = t; + } + break; + } + case 'T': + { + size_t k0 = db.names.size(); + t = parse_template_param(first, last, db); + size_t k1 = db.names.size(); + if (t != first) + { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + db.subs.back().push_back(db.names[k]); + if (db.try_to_parse_template_args && k1 == k0+1) + { + const char* t1 = parse_template_args(t, last, db); + if (t1 != t) + { + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + t = t1; + } + } + first = t; + } + break; + } + case 'U': + if (first+1 != last) + { + t = parse_source_name(first+1, last, db); + if (t != first+1) + { + const char* t2 = parse_type(t, last, db); + if (t2 != t) + { + if (db.names.size() < 2) + return first; + auto type = db.names.back().move_full(); + db.names.pop_back(); + if (db.names.back().first.substr(0, 9) != "objcproto") + { + db.names.back() = type + " " + db.names.back().move_full(); + } + else + { + auto proto = db.names.back().move_full(); + db.names.pop_back(); + t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db); + if (t != proto.data() + 9) + { + db.names.back() = type + "<" + db.names.back().move_full() + ">"; + } + else + { + db.names.push_back(type + " " + proto); + } + } + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t2; + } + } + } + break; + case 'S': + if (first+1 != last && first[1] == 't') + { + t = parse_name(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + } + else + { + t = parse_substitution(first, last, db); + if (t != first) + { + first = t; + // Parsed a substitution. If the substitution is a + // it might be followed by . + t = parse_template_args(first, last, db); + if (t != first) + { + if (db.names.size() < 2) + return first; + auto template_args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += template_args; + // Need to create substitution for + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + } + } + break; + case 'D': + if (first+1 != last) + { + switch (first[1]) + { + case 'p': + { + size_t k0 = db.names.size(); + t = parse_type(first+2, last, db); + size_t k1 = db.names.size(); + if (t != first+2) + { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + db.subs.back().push_back(db.names[k]); + first = t; + return first; + } + break; + } + case 't': + case 'T': + t = parse_decltype(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + return first; + } + break; + case 'v': + t = parse_vector_type(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + return first; + } + break; + } + } + // drop through + default: + // must check for builtin-types before class-enum-types to avoid + // ambiguities with operator-names + t = parse_builtin_type(first, last, db); + if (t != first) + { + first = t; + } + else + { + t = parse_name(first, last, db); + if (t != first) + { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + } + break; + } + } + break; + } + } + } + return first; +} + +// +// ::= aa # && +// ::= ad # & (unary) +// ::= an # & +// ::= aN # &= +// ::= aS # = +// ::= cl # () +// ::= cm # , +// ::= co # ~ +// ::= cv # (cast) +// ::= da # delete[] +// ::= de # * (unary) +// ::= dl # delete +// ::= dv # / +// ::= dV # /= +// ::= eo # ^ +// ::= eO # ^= +// ::= eq # == +// ::= ge # >= +// ::= gt # > +// ::= ix # [] +// ::= le # <= +// ::= li # operator "" +// ::= ls # << +// ::= lS # <<= +// ::= lt # < +// ::= mi # - +// ::= mI # -= +// ::= ml # * +// ::= mL # *= +// ::= mm # -- (postfix in context) +// ::= na # new[] +// ::= ne # != +// ::= ng # - (unary) +// ::= nt # ! +// ::= nw # new +// ::= oo # || +// ::= or # | +// ::= oR # |= +// ::= pm # ->* +// ::= pl # + +// ::= pL # += +// ::= pp # ++ (postfix in context) +// ::= ps # + (unary) +// ::= pt # -> +// ::= qu # ? +// ::= rm # % +// ::= rM # %= +// ::= rs # >> +// ::= rS # >>= +// ::= v # vendor extended operator + +template +const char* +parse_operator_name(const char* first, const char* last, C& db) +{ + if (last - first >= 2) + { + switch (first[0]) + { + case 'a': + switch (first[1]) + { + case 'a': + db.names.push_back("operator&&"); + first += 2; + break; + case 'd': + case 'n': + db.names.push_back("operator&"); + first += 2; + break; + case 'N': + db.names.push_back("operator&="); + first += 2; + break; + case 'S': + db.names.push_back("operator="); + first += 2; + break; + } + break; + case 'c': + switch (first[1]) + { + case 'l': + db.names.push_back("operator()"); + first += 2; + break; + case 'm': + db.names.push_back("operator,"); + first += 2; + break; + case 'o': + db.names.push_back("operator~"); + first += 2; + break; + case 'v': + { + bool try_to_parse_template_args = db.try_to_parse_template_args; + db.try_to_parse_template_args = false; + const char* t = parse_type(first+2, last, db); + db.try_to_parse_template_args = try_to_parse_template_args; + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator "); + db.parsed_ctor_dtor_cv = true; + first = t; + } + } + break; + } + break; + case 'd': + switch (first[1]) + { + case 'a': + db.names.push_back("operator delete[]"); + first += 2; + break; + case 'e': + db.names.push_back("operator*"); + first += 2; + break; + case 'l': + db.names.push_back("operator delete"); + first += 2; + break; + case 'v': + db.names.push_back("operator/"); + first += 2; + break; + case 'V': + db.names.push_back("operator/="); + first += 2; + break; + } + break; + case 'e': + switch (first[1]) + { + case 'o': + db.names.push_back("operator^"); + first += 2; + break; + case 'O': + db.names.push_back("operator^="); + first += 2; + break; + case 'q': + db.names.push_back("operator=="); + first += 2; + break; + } + break; + case 'g': + switch (first[1]) + { + case 'e': + db.names.push_back("operator>="); + first += 2; + break; + case 't': + db.names.push_back("operator>"); + first += 2; + break; + } + break; + case 'i': + if (first[1] == 'x') + { + db.names.push_back("operator[]"); + first += 2; + } + break; + case 'l': + switch (first[1]) + { + case 'e': + db.names.push_back("operator<="); + first += 2; + break; + case 'i': + { + const char* t = parse_source_name(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator\"\" "); + first = t; + } + } + break; + case 's': + db.names.push_back("operator<<"); + first += 2; + break; + case 'S': + db.names.push_back("operator<<="); + first += 2; + break; + case 't': + db.names.push_back("operator<"); + first += 2; + break; + } + break; + case 'm': + switch (first[1]) + { + case 'i': + db.names.push_back("operator-"); + first += 2; + break; + case 'I': + db.names.push_back("operator-="); + first += 2; + break; + case 'l': + db.names.push_back("operator*"); + first += 2; + break; + case 'L': + db.names.push_back("operator*="); + first += 2; + break; + case 'm': + db.names.push_back("operator--"); + first += 2; + break; + } + break; + case 'n': + switch (first[1]) + { + case 'a': + db.names.push_back("operator new[]"); + first += 2; + break; + case 'e': + db.names.push_back("operator!="); + first += 2; + break; + case 'g': + db.names.push_back("operator-"); + first += 2; + break; + case 't': + db.names.push_back("operator!"); + first += 2; + break; + case 'w': + db.names.push_back("operator new"); + first += 2; + break; + } + break; + case 'o': + switch (first[1]) + { + case 'o': + db.names.push_back("operator||"); + first += 2; + break; + case 'r': + db.names.push_back("operator|"); + first += 2; + break; + case 'R': + db.names.push_back("operator|="); + first += 2; + break; + } + break; + case 'p': + switch (first[1]) + { + case 'm': + db.names.push_back("operator->*"); + first += 2; + break; + case 'l': + db.names.push_back("operator+"); + first += 2; + break; + case 'L': + db.names.push_back("operator+="); + first += 2; + break; + case 'p': + db.names.push_back("operator++"); + first += 2; + break; + case 's': + db.names.push_back("operator+"); + first += 2; + break; + case 't': + db.names.push_back("operator->"); + first += 2; + break; + } + break; + case 'q': + if (first[1] == 'u') + { + db.names.push_back("operator?"); + first += 2; + } + break; + case 'r': + switch (first[1]) + { + case 'm': + db.names.push_back("operator%"); + first += 2; + break; + case 'M': + db.names.push_back("operator%="); + first += 2; + break; + case 's': + db.names.push_back("operator>>"); + first += 2; + break; + case 'S': + db.names.push_back("operator>>="); + first += 2; + break; + } + break; + case 'v': + if (std::isdigit(first[1])) + { + const char* t = parse_source_name(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator "); + first = t; + } + } + break; + } + } + return first; +} + +template +const char* +parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db) +{ + const char* t = parse_number(first, last); + if (t != first && t != last && *t == 'E') + { + if (lit.size() > 3) + db.names.push_back("(" + lit + ")"); + else + db.names.emplace_back(); + if (*first == 'n') + { + db.names.back().first += '-'; + ++first; + } + db.names.back().first.append(first, t); + if (lit.size() <= 3) + db.names.back().first += lit; + first = t+1; + } + return first; +} + +// ::= L E # integer literal +// ::= L E # floating literal +// ::= L E # string literal +// ::= L E # nullptr literal (i.e., "LDnE") +// ::= L _ E # complex floating point literal (C 2000) +// ::= L E # external name + +template +const char* +parse_expr_primary(const char* first, const char* last, C& db) +{ + if (last - first >= 4 && *first == 'L') + { + switch (first[1]) + { + case 'w': + { + const char* t = parse_integer_literal(first+2, last, "wchar_t", db); + if (t != first+2) + first = t; + } + break; + case 'b': + if (first[3] == 'E') + { + switch (first[2]) + { + case '0': + db.names.push_back("false"); + first += 4; + break; + case '1': + db.names.push_back("true"); + first += 4; + break; + } + } + break; + case 'c': + { + const char* t = parse_integer_literal(first+2, last, "char", db); + if (t != first+2) + first = t; + } + break; + case 'a': + { + const char* t = parse_integer_literal(first+2, last, "signed char", db); + if (t != first+2) + first = t; + } + break; + case 'h': + { + const char* t = parse_integer_literal(first+2, last, "unsigned char", db); + if (t != first+2) + first = t; + } + break; + case 's': + { + const char* t = parse_integer_literal(first+2, last, "short", db); + if (t != first+2) + first = t; + } + break; + case 't': + { + const char* t = parse_integer_literal(first+2, last, "unsigned short", db); + if (t != first+2) + first = t; + } + break; + case 'i': + { + const char* t = parse_integer_literal(first+2, last, "", db); + if (t != first+2) + first = t; + } + break; + case 'j': + { + const char* t = parse_integer_literal(first+2, last, "u", db); + if (t != first+2) + first = t; + } + break; + case 'l': + { + const char* t = parse_integer_literal(first+2, last, "l", db); + if (t != first+2) + first = t; + } + break; + case 'm': + { + const char* t = parse_integer_literal(first+2, last, "ul", db); + if (t != first+2) + first = t; + } + break; + case 'x': + { + const char* t = parse_integer_literal(first+2, last, "ll", db); + if (t != first+2) + first = t; + } + break; + case 'y': + { + const char* t = parse_integer_literal(first+2, last, "ull", db); + if (t != first+2) + first = t; + } + break; + case 'n': + { + const char* t = parse_integer_literal(first+2, last, "__int128", db); + if (t != first+2) + first = t; + } + break; + case 'o': + { + const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db); + if (t != first+2) + first = t; + } + break; + case 'f': + { + const char* t = parse_floating_number(first+2, last, db); + if (t != first+2) + first = t; + } + break; + case 'd': + { + const char* t = parse_floating_number(first+2, last, db); + if (t != first+2) + first = t; + } + break; + case 'e': + { + const char* t = parse_floating_number(first+2, last, db); + if (t != first+2) + first = t; + } + break; + case '_': + if (first[2] == 'Z') + { + const char* t = parse_encoding(first+3, last, db); + if (t != first+3 && t != last && *t == 'E') + first = t+1; + } + break; + case 'T': + // Invalid mangled name per + // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html + break; + default: + { + // might be named type + const char* t = parse_type(first+1, last, db); + if (t != first+1 && t != last) + { + if (*t != 'E') + { + const char* n = t; + for (; n != last && isdigit(*n); ++n) + ; + if (n != t && n != last && *n == 'E') + { + if (db.names.empty()) + return first; + db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n); + first = n+1; + break; + } + } + else + { + first = t+1; + break; + } + } + } + } + } + return first; +} + +template +String +base_name(String& s) +{ + if (s.empty()) + return s; + if (s == "std::string") + { + s = "std::basic_string, std::allocator >"; + return "basic_string"; + } + if (s == "std::istream") + { + s = "std::basic_istream >"; + return "basic_istream"; + } + if (s == "std::ostream") + { + s = "std::basic_ostream >"; + return "basic_ostream"; + } + if (s == "std::iostream") + { + s = "std::basic_iostream >"; + return "basic_iostream"; + } + const char* const pf = s.data(); + const char* pe = pf + s.size(); + if (pe[-1] == '>') + { + unsigned c = 1; + while (true) + { + if (--pe == pf) + return String(); + if (pe[-1] == '<') + { + if (--c == 0) + { + --pe; + break; + } + } + else if (pe[-1] == '>') + ++c; + } + } + const char* p0 = pe - 1; + for (; p0 != pf; --p0) + { + if (*p0 == ':') + { + ++p0; + break; + } + } + return String(p0, pe); +} + +// ::= C1 # complete object constructor +// ::= C2 # base object constructor +// ::= C3 # complete object allocating constructor +// extension ::= C5 # ? +// ::= D0 # deleting destructor +// ::= D1 # complete object destructor +// ::= D2 # base object destructor +// extension ::= D5 # ? + +template +const char* +parse_ctor_dtor_name(const char* first, const char* last, C& db) +{ + if (last-first >= 2 && !db.names.empty()) + { + switch (first[0]) + { + case 'C': + switch (first[1]) + { + case '1': + case '2': + case '3': + case '5': + if (db.names.empty()) + return first; + db.names.push_back(base_name(db.names.back().first)); + first += 2; + db.parsed_ctor_dtor_cv = true; + break; + } + break; + case 'D': + switch (first[1]) + { + case '0': + case '1': + case '2': + case '5': + if (db.names.empty()) + return first; + db.names.push_back("~" + base_name(db.names.back().first)); + first += 2; + db.parsed_ctor_dtor_cv = true; + break; + } + break; + } + } + return first; +} + +// ::= Ut [ ] _ +// ::= +// +// ::= Ul E [ ] _ +// +// ::= + # Parameter types or "v" if the lambda has no parameters + +template +const char* +parse_unnamed_type_name(const char* first, const char* last, C& db) +{ + if (last - first > 2 && first[0] == 'U') + { + char type = first[1]; + switch (type) + { + case 't': + { + db.names.push_back(typename C::String("'unnamed")); + const char* t0 = first+2; + if (t0 == last) + { + db.names.pop_back(); + return first; + } + if (std::isdigit(*t0)) + { + const char* t1 = t0 + 1; + while (t1 != last && std::isdigit(*t1)) + ++t1; + db.names.back().first.append(t0, t1); + t0 = t1; + } + db.names.back().first.push_back('\''); + if (t0 == last || *t0 != '_') + { + db.names.pop_back(); + return first; + } + first = t0 + 1; + } + break; + case 'l': + { + db.names.push_back(typename C::String("'lambda'(")); + const char* t0 = first+2; + if (first[2] == 'v') + { + db.names.back().first += ')'; + ++t0; + } + else + { + const char* t1 = parse_type(t0, last, db); + if (t1 == t0) + { + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first.append(tmp); + t0 = t1; + while (true) + { + t1 = parse_type(t0, last, db); + if (t1 == t0) + break; + if (db.names.size() < 2) + return first; + tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) + { + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + } + t0 = t1; + } + db.names.back().first.append(")"); + } + if (t0 == last || *t0 != 'E') + { + db.names.pop_back(); + return first; + } + ++t0; + if (t0 == last) + { + db.names.pop_back(); + return first; + } + if (std::isdigit(*t0)) + { + const char* t1 = t0 + 1; + while (t1 != last && std::isdigit(*t1)) + ++t1; + db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1); + t0 = t1; + } + if (t0 == last || *t0 != '_') + { + db.names.pop_back(); + return first; + } + first = t0 + 1; + } + break; + } + } + return first; +} + +// ::= +// ::= +// ::= +// ::= + +template +const char* +parse_unqualified_name(const char* first, const char* last, C& db) +{ + if (first != last) + { + const char* t; + switch (*first) + { + case 'C': + case 'D': + t = parse_ctor_dtor_name(first, last, db); + if (t != first) + first = t; + break; + case 'U': + t = parse_unnamed_type_name(first, last, db); + if (t != first) + first = t; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + t = parse_source_name(first, last, db); + if (t != first) + first = t; + break; + default: + t = parse_operator_name(first, last, db); + if (t != first) + first = t; + break; + }; + } + return first; +} + +// ::= +// ::= St # ::std:: +// extension ::= StL + +template +const char* +parse_unscoped_name(const char* first, const char* last, C& db) +{ + if (last - first >= 2) + { + const char* t0 = first; + bool St = false; + if (first[0] == 'S' && first[1] == 't') + { + t0 += 2; + St = true; + if (t0 != last && *t0 == 'L') + ++t0; + } + const char* t1 = parse_unqualified_name(t0, last, db); + if (t1 != t0) + { + if (St) + { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "std::"); + } + first = t1; + } + } + return first; +} + +// at # alignof (a type) + +template +const char* +parse_alignof_type(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'a' && first[1] == 't') + { + const char* t = parse_type(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; + first = t; + } + } + return first; +} + +// az # alignof (a expression) + +template +const char* +parse_alignof_expr(const char* first, const char* last, C& db) +{ + if (last - first >= 3 && first[0] == 'a' && first[1] == 'z') + { + const char* t = parse_expression(first+2, last, db); + if (t != first+2) + { + if (db.names.empty()) + return first; + db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; + first = t; + } + } + return first; +} + +template +const char* +parse_noexcept_expression(const char* first, const char* last, C& db) +{ + const char* t1 = parse_expression(first, last, db); + if (t1 != first) + { + if (db.names.empty()) + return first; + db.names.back().first = "noexcept (" + db.names.back().move_full() + ")"; + first = t1; + } + return first; +} + +template +const char* +parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db) +{ + const char* t1 = parse_expression(first, last, db); + if (t1 != first) + { + if (db.names.empty()) + return first; + db.names.back().first = op + "(" + db.names.back().move_full() + ")"; + first = t1; + } + return first; +} + +template +const char* +parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db) +{ + const char* t1 = parse_expression(first, last, db); + if (t1 != first) + { + const char* t2 = parse_expression(t1, last, db); + if (t2 != t1) + { + if (db.names.size() < 2) + return first; + auto op2 = db.names.back().move_full(); + db.names.pop_back(); + auto op1 = db.names.back().move_full(); + auto& nm = db.names.back().first; + nm.clear(); + if (op == ">") + nm += '('; + nm += "(" + op1 + ") " + op + " (" + op2 + ")"; + if (op == ">") + nm += ')'; + first = t2; + } + else + db.names.pop_back(); + } + return first; +} + +// ::= +// ::= +// ::= +// ::= cl + E # call +// ::= cv # conversion with one argument +// ::= cv _ * E # conversion with a different number of arguments +// ::= [gs] nw * _ E # new (expr-list) type +// ::= [gs] nw * _ # new (expr-list) type (init) +// ::= [gs] na * _ E # new[] (expr-list) type +// ::= [gs] na * _ # new[] (expr-list) type (init) +// ::= [gs] dl # delete expression +// ::= [gs] da # delete[] expression +// ::= pp_ # prefix ++ +// ::= mm_ # prefix -- +// ::= ti # typeid (type) +// ::= te # typeid (expression) +// ::= dc # dynamic_cast (expression) +// ::= sc # static_cast (expression) +// ::= cc # const_cast (expression) +// ::= rc # reinterpret_cast (expression) +// ::= st # sizeof (a type) +// ::= sz # sizeof (an expression) +// ::= at # alignof (a type) +// ::= az # alignof (an expression) +// ::= nx # noexcept (expression) +// ::= +// ::= +// ::= dt # expr.name +// ::= pt # expr->name +// ::= ds # expr.*expr +// ::= sZ # size of a parameter pack +// ::= sZ # size of a function parameter pack +// ::= sp # pack expansion +// ::= tw # throw expression +// ::= tr # throw with no operand (rethrow) +// ::= # f(p), N::f(p), ::f(p), +// # freestanding dependent name (e.g., T::x), +// # objectless nonstatic member reference +// ::= + +template +const char* +parse_expression(const char* first, const char* last, C& db) +{ + if (last - first >= 2) + { + const char* t = first; + bool parsed_gs = false; + if (last - first >= 4 && t[0] == 'g' && t[1] == 's') + { + t += 2; + parsed_gs = true; + } + switch (*t) + { + case 'L': + first = parse_expr_primary(first, last, db); + break; + case 'T': + first = parse_template_param(first, last, db); + break; + case 'f': + first = parse_function_param(first, last, db); + break; + case 'a': + switch (t[1]) + { + case 'a': + t = parse_binary_expression(first+2, last, "&&", db); + if (t != first+2) + first = t; + break; + case 'd': + t = parse_prefix_expression(first+2, last, "&", db); + if (t != first+2) + first = t; + break; + case 'n': + t = parse_binary_expression(first+2, last, "&", db); + if (t != first+2) + first = t; + break; + case 'N': + t = parse_binary_expression(first+2, last, "&=", db); + if (t != first+2) + first = t; + break; + case 'S': + t = parse_binary_expression(first+2, last, "=", db); + if (t != first+2) + first = t; + break; + case 't': + first = parse_alignof_type(first, last, db); + break; + case 'z': + first = parse_alignof_expr(first, last, db); + break; + } + break; + case 'c': + switch (t[1]) + { + case 'c': + first = parse_const_cast_expr(first, last, db); + break; + case 'l': + first = parse_call_expr(first, last, db); + break; + case 'm': + t = parse_binary_expression(first+2, last, ",", db); + if (t != first+2) + first = t; + break; + case 'o': + t = parse_prefix_expression(first+2, last, "~", db); + if (t != first+2) + first = t; + break; + case 'v': + first = parse_conversion_expr(first, last, db); + break; + } + break; + case 'd': + switch (t[1]) + { + case 'a': + { + const char* t1 = parse_expression(t+2, last, db); + if (t1 != t+2) + { + if (db.names.empty()) + return first; + db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + + "delete[] " + db.names.back().move_full(); + first = t1; + } + } + break; + case 'c': + first = parse_dynamic_cast_expr(first, last, db); + break; + case 'e': + t = parse_prefix_expression(first+2, last, "*", db); + if (t != first+2) + first = t; + break; + case 'l': + { + const char* t1 = parse_expression(t+2, last, db); + if (t1 != t+2) + { + if (db.names.empty()) + return first; + db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + + "delete " + db.names.back().move_full(); + first = t1; + } + } + break; + case 'n': + return parse_unresolved_name(first, last, db); + case 's': + first = parse_dot_star_expr(first, last, db); + break; + case 't': + first = parse_dot_expr(first, last, db); + break; + case 'v': + t = parse_binary_expression(first+2, last, "/", db); + if (t != first+2) + first = t; + break; + case 'V': + t = parse_binary_expression(first+2, last, "/=", db); + if (t != first+2) + first = t; + break; + } + break; + case 'e': + switch (t[1]) + { + case 'o': + t = parse_binary_expression(first+2, last, "^", db); + if (t != first+2) + first = t; + break; + case 'O': + t = parse_binary_expression(first+2, last, "^=", db); + if (t != first+2) + first = t; + break; + case 'q': + t = parse_binary_expression(first+2, last, "==", db); + if (t != first+2) + first = t; + break; + } + break; + case 'g': + switch (t[1]) + { + case 'e': + t = parse_binary_expression(first+2, last, ">=", db); + if (t != first+2) + first = t; + break; + case 't': + t = parse_binary_expression(first+2, last, ">", db); + if (t != first+2) + first = t; + break; + } + break; + case 'i': + if (t[1] == 'x') + { + const char* t1 = parse_expression(first+2, last, db); + if (t1 != first+2) + { + const char* t2 = parse_expression(t1, last, db); + if (t2 != t1) + { + if (db.names.size() < 2) + return first; + auto op2 = db.names.back().move_full(); + db.names.pop_back(); + auto op1 = db.names.back().move_full(); + db.names.back() = "(" + op1 + ")[" + op2 + "]"; + first = t2; + } + else + db.names.pop_back(); + } + } + break; + case 'l': + switch (t[1]) + { + case 'e': + t = parse_binary_expression(first+2, last, "<=", db); + if (t != first+2) + first = t; + break; + case 's': + t = parse_binary_expression(first+2, last, "<<", db); + if (t != first+2) + first = t; + break; + case 'S': + t = parse_binary_expression(first+2, last, "<<=", db); + if (t != first+2) + first = t; + break; + case 't': + t = parse_binary_expression(first+2, last, "<", db); + if (t != first+2) + first = t; + break; + } + break; + case 'm': + switch (t[1]) + { + case 'i': + t = parse_binary_expression(first+2, last, "-", db); + if (t != first+2) + first = t; + break; + case 'I': + t = parse_binary_expression(first+2, last, "-=", db); + if (t != first+2) + first = t; + break; + case 'l': + t = parse_binary_expression(first+2, last, "*", db); + if (t != first+2) + first = t; + break; + case 'L': + t = parse_binary_expression(first+2, last, "*=", db); + if (t != first+2) + first = t; + break; + case 'm': + if (first+2 != last && first[2] == '_') + { + t = parse_prefix_expression(first+3, last, "--", db); + if (t != first+3) + first = t; + } + else + { + const char* t1 = parse_expression(first+2, last, db); + if (t1 != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "(" + db.names.back().move_full() + ")--"; + first = t1; + } + } + break; + } + break; + case 'n': + switch (t[1]) + { + case 'a': + case 'w': + first = parse_new_expr(first, last, db); + break; + case 'e': + t = parse_binary_expression(first+2, last, "!=", db); + if (t != first+2) + first = t; + break; + case 'g': + t = parse_prefix_expression(first+2, last, "-", db); + if (t != first+2) + first = t; + break; + case 't': + t = parse_prefix_expression(first+2, last, "!", db); + if (t != first+2) + first = t; + break; + case 'x': + t = parse_noexcept_expression(first+2, last, db); + if (t != first+2) + first = t; + break; + } + break; + case 'o': + switch (t[1]) + { + case 'n': + return parse_unresolved_name(first, last, db); + case 'o': + t = parse_binary_expression(first+2, last, "||", db); + if (t != first+2) + first = t; + break; + case 'r': + t = parse_binary_expression(first+2, last, "|", db); + if (t != first+2) + first = t; + break; + case 'R': + t = parse_binary_expression(first+2, last, "|=", db); + if (t != first+2) + first = t; + break; + } + break; + case 'p': + switch (t[1]) + { + case 'm': + t = parse_binary_expression(first+2, last, "->*", db); + if (t != first+2) + first = t; + break; + case 'l': + t = parse_binary_expression(first+2, last, "+", db); + if (t != first+2) + first = t; + break; + case 'L': + t = parse_binary_expression(first+2, last, "+=", db); + if (t != first+2) + first = t; + break; + case 'p': + if (first+2 != last && first[2] == '_') + { + t = parse_prefix_expression(first+3, last, "++", db); + if (t != first+3) + first = t; + } + else + { + const char* t1 = parse_expression(first+2, last, db); + if (t1 != first+2) + { + if (db.names.empty()) + return first; + db.names.back() = "(" + db.names.back().move_full() + ")++"; + first = t1; + } + } + break; + case 's': + t = parse_prefix_expression(first+2, last, "+", db); + if (t != first+2) + first = t; + break; + case 't': + first = parse_arrow_expr(first, last, db); + break; + } + break; + case 'q': + if (t[1] == 'u') + { + const char* t1 = parse_expression(first+2, last, db); + if (t1 != first+2) + { + const char* t2 = parse_expression(t1, last, db); + if (t2 != t1) + { + const char* t3 = parse_expression(t2, last, db); + if (t3 != t2) + { + if (db.names.size() < 3) + return first; + auto op3 = db.names.back().move_full(); + db.names.pop_back(); + auto op2 = db.names.back().move_full(); + db.names.pop_back(); + auto op1 = db.names.back().move_full(); + db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")"; + first = t3; + } + else + { + db.names.pop_back(); + db.names.pop_back(); + } + } + else + db.names.pop_back(); + } + } + break; + case 'r': + switch (t[1]) + { + case 'c': + first = parse_reinterpret_cast_expr(first, last, db); + break; + case 'm': + t = parse_binary_expression(first+2, last, "%", db); + if (t != first+2) + first = t; + break; + case 'M': + t = parse_binary_expression(first+2, last, "%=", db); + if (t != first+2) + first = t; + break; + case 's': + t = parse_binary_expression(first+2, last, ">>", db); + if (t != first+2) + first = t; + break; + case 'S': + t = parse_binary_expression(first+2, last, ">>=", db); + if (t != first+2) + first = t; + break; + } + break; + case 's': + switch (t[1]) + { + case 'c': + first = parse_static_cast_expr(first, last, db); + break; + case 'p': + first = parse_pack_expansion(first, last, db); + break; + case 'r': + return parse_unresolved_name(first, last, db); + case 't': + first = parse_sizeof_type_expr(first, last, db); + break; + case 'z': + first = parse_sizeof_expr_expr(first, last, db); + break; + case 'Z': + if (last - t >= 3) + { + switch (t[2]) + { + case 'T': + first = parse_sizeof_param_pack_expr(first, last, db); + break; + case 'f': + first = parse_sizeof_function_param_pack_expr(first, last, db); + break; + } + } + break; + } + break; + case 't': + switch (t[1]) + { + case 'e': + case 'i': + first = parse_typeid_expr(first, last, db); + break; + case 'r': + db.names.push_back("throw"); + first += 2; + break; + case 'w': + first = parse_throw_expr(first, last, db); + break; + } + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return parse_unresolved_name(first, last, db); + } + } + return first; +} + +// ::= # type or template +// ::= X E # expression +// ::= # simple expressions +// ::= J * E # argument pack +// ::= LZ E # extension + +template +const char* +parse_template_arg(const char* first, const char* last, C& db) +{ + if (first != last) + { + const char* t; + switch (*first) + { + case 'X': + t = parse_expression(first+1, last, db); + if (t != first+1) + { + if (t != last && *t == 'E') + first = t+1; + } + break; + case 'J': + t = first+1; + if (t == last) + return first; + while (*t != 'E') + { + const char* t1 = parse_template_arg(t, last, db); + if (t1 == t) + return first; + t = t1; + } + first = t+1; + break; + case 'L': + // or LZ E + if (first+1 != last && first[1] == 'Z') + { + t = parse_encoding(first+2, last, db); + if (t != first+2 && t != last && *t == 'E') + first = t+1; + } + else + first = parse_expr_primary(first, last, db); + break; + default: + // + first = parse_type(first, last, db); + break; + } + } + return first; +} + +// ::= I * E +// extension, the abi says + + +template +const char* +parse_template_args(const char* first, const char* last, C& db) +{ + if (last - first >= 2 && *first == 'I') + { + if (db.tag_templates) + db.template_param.back().clear(); + const char* t = first+1; + typename C::String args("<"); + while (*t != 'E') + { + if (db.tag_templates) + db.template_param.emplace_back(db.names.get_allocator()); + size_t k0 = db.names.size(); + const char* t1 = parse_template_arg(t, last, db); + size_t k1 = db.names.size(); + if (db.tag_templates) + db.template_param.pop_back(); + if (t1 == t || t1 == last) + return first; + if (db.tag_templates) + { + db.template_param.back().emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + db.template_param.back().back().push_back(db.names[k]); + } + for (size_t k = k0; k < k1; ++k) + { + if (args.size() > 1) + args += ", "; + args += db.names[k].move_full(); + } + for (; k1 != k0; --k1) + db.names.pop_back(); + t = t1; + } + first = t + 1; + if (args.back() != '>') + args += ">"; + else + args += " >"; + db.names.push_back(std::move(args)); + + } + return first; +} + +// ::= N [] [] E +// ::= N [] [] E +// +// ::= +// ::= +// ::= +// ::= +// ::= # empty +// ::= +// ::= +// extension ::= L +// +// ::=