diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-13 19:26:17 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-13 19:26:17 +0000 |
commit | e75e363cb71a7339552b9d943e78ac62b737379b (patch) | |
tree | 29ec5bd173694acbbcbb8207114ef7ca189436ba | |
parent | 1b306c26ade71504511d2fa75b03dfaee77f9620 (diff) |
Vendor import of lldb trunk r307894:vendor/lldb/lldb-trunk-r307894
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=320967
svn path=/vendor/lldb/lldb-trunk-r307894/; revision=320968; tag=vendor/lldb/lldb-trunk-r307894
78 files changed, 1151 insertions, 1485 deletions
diff --git a/docs/lldb-gdb-remote.txt b/docs/lldb-gdb-remote.txt index a4427a70444d..0000738b556b 100644 --- a/docs/lldb-gdb-remote.txt +++ b/docs/lldb-gdb-remote.txt @@ -126,6 +126,32 @@ read packet: $OK#00 This packet can be sent one or more times _prior_ to sending a "A" packet. //---------------------------------------------------------------------- +// "QEnableErrorStrings" +// +// BRIEF +// This packet enables reporting of Error strings in remote packet +// replies from the server to client. If the server supports this +// feature, it should send an OK response. The client can expect the +// following error replies if this feature is enabled in the server -> +// +// EXX;AAAAAAAAA +// +// where AAAAAAAAA will be a hex encoded ASCII string. +// XX is hex encoded byte number. +// +// It must be noted that even if the client has enabled reporting +// strings in error replies, it must not expect error strings to all +// error replies. +// +// PRIORITY TO IMPLEMENT +// Low. Only needed if the remote target wants to provide strings that +// are human readable along with an error code. +//---------------------------------------------------------------------- + +send packet: $QErrorStringInPacketSupported +read packet: $OK#00 + +//---------------------------------------------------------------------- // "QSetSTDIN:<ascii-hex-path>" // "QSetSTDOUT:<ascii-hex-path>" // "QSetSTDERR:<ascii-hex-path>" @@ -250,11 +276,12 @@ read packet: OK // // Each tracing instance is identified by a trace id which is returned // as the reply to this packet. In case the tracing failed to begin an -// error code is returned instead. +// error code along with a hex encoded ASCII message is returned +// instead. //---------------------------------------------------------------------- send packet: jTraceStart:{"type":<type>,"buffersize":<buffersize>}] -read packet: <trace id>/E<error code> +read packet: <trace id>/E<error code>;AAAAAAAAA //---------------------------------------------------------------------- // jTraceStop: @@ -283,12 +310,12 @@ read packet: <trace id>/E<error code> // to stop tracing on that thread. // ========== ==================================================== // -// An OK response is sent in case of success else an error code is -// returned. +// An OK response is sent in case of success else an error code along +// with a hex encoded ASCII message is returned. //---------------------------------------------------------------------- send packet: jTraceStop:{"traceid":<trace id>}] -read packet: <OK response>/E<error code> +read packet: <OK response>/E<error code>;AAAAAAAAA //---------------------------------------------------------------------- // jTraceBufferRead: @@ -317,11 +344,11 @@ read packet: <OK response>/E<error code> // ========== ==================================================== // // The trace data is sent as raw binary data if the read was successful -// else an error code is sent. +// else an error code along with a hex encoded ASCII message is sent. //---------------------------------------------------------------------- send packet: jTraceBufferRead:{"traceid":<trace id>,"offset":<byteoffset>,"buffersize":<byte_count>}] -read packet: <binary trace data>/E<error code> +read packet: <binary trace data>/E<error code>;AAAAAAAAA //---------------------------------------------------------------------- // jTraceMetaRead: @@ -359,11 +386,11 @@ read packet: <binary trace data>/E<error code> // gdb-remote protocol has certain limitations, binary escaping // convention is used. // In case the trace instance with the <trace id> was not found, an -// error code is returned. +// error code along with a hex encoded ASCII message is returned. //---------------------------------------------------------------------- send packet: jTraceConfigRead:{"traceid":<trace id>} -read packet: {"conf1":<conf1>,"conf2":<conf2>,"params":{"paramName":paramValue}]}];/E<error code> +read packet: {"conf1":<conf1>,"conf2":<conf2>,"params":{"paramName":paramValue}]}];/E<error code>;AAAAAAAAA //---------------------------------------------------------------------- // "qRegisterInfo<hex-reg-id>" diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h index c41e4796f532..da0b8e14c4a7 100644 --- a/include/lldb/Host/Host.h +++ b/include/lldb/Host/Host.h @@ -7,14 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Host_h_ -#define liblldb_Host_h_ -#if defined(__cplusplus) - -#include <stdarg.h> - -#include <map> -#include <string> +#ifndef LLDB_HOST_HOST_H +#define LLDB_HOST_HOST_H #include "lldb/Host/File.h" #include "lldb/Host/HostThread.h" @@ -22,6 +16,11 @@ #include "lldb/Utility/StringList.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-private.h" +#include <cerrno> +#include <map> +#include <stdarg.h> +#include <string> +#include <type_traits> namespace lldb_private { @@ -254,5 +253,4 @@ template <> struct format_provider<lldb_private::WaitStatus> { }; } // namespace llvm -#endif // #if defined(__cplusplus) -#endif // liblldb_Host_h_ +#endif // LLDB_HOST_HOST_H diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h index a97540499cd3..5f2157510c0a 100644 --- a/include/lldb/Host/common/NativeProcessProtocol.h +++ b/include/lldb/Host/common/NativeProcessProtocol.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include <vector> @@ -244,68 +245,57 @@ public: virtual Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) = 0; - //------------------------------------------------------------------ - /// Launch a process for debugging. This method will create an concrete - /// instance of NativeProcessProtocol, based on the host platform. - /// (e.g. NativeProcessLinux on linux, etc.) - /// - /// @param[in] launch_info - /// Information required to launch the process. - /// - /// @param[in] native_delegate - /// The delegate that will receive messages regarding the - /// inferior. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[in] mainloop - /// The mainloop instance with which the process can register - /// callbacks. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[out] process_sp - /// On successful return from the method, this parameter - /// contains the shared pointer to the - /// NativeProcessProtocol that can be used to manipulate - /// the native process. - /// - /// @return - /// An error object indicating if the operation succeeded, - /// and if not, what error occurred. - //------------------------------------------------------------------ - static Status Launch(ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &process_sp); - - //------------------------------------------------------------------ - /// Attach to an existing process. This method will create an concrete - /// instance of NativeProcessProtocol, based on the host platform. - /// (e.g. NativeProcessLinux on linux, etc.) - /// - /// @param[in] pid - /// pid of the process locatable - /// - /// @param[in] native_delegate - /// The delegate that will receive messages regarding the - /// inferior. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[in] mainloop - /// The mainloop instance with which the process can register - /// callbacks. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[out] process_sp - /// On successful return from the method, this parameter - /// contains the shared pointer to the - /// NativeProcessProtocol that can be used to manipulate - /// the native process. - /// - /// @return - /// An error object indicating if the operation succeeded, - /// and if not, what error occurred. - //------------------------------------------------------------------ - static Status Attach(lldb::pid_t pid, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + class Factory { + public: + virtual ~Factory(); + //------------------------------------------------------------------ + /// Launch a process for debugging. + /// + /// @param[in] launch_info + /// Information required to launch the process. + /// + /// @param[in] native_delegate + /// The delegate that will receive messages regarding the + /// inferior. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @param[in] mainloop + /// The mainloop instance with which the process can register + /// callbacks. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @return + /// A NativeProcessProtocol shared pointer if the operation succeeded or + /// an error object if it failed. + //------------------------------------------------------------------ + virtual llvm::Expected<NativeProcessProtocolSP> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const = 0; + + //------------------------------------------------------------------ + /// Attach to an existing process. + /// + /// @param[in] pid + /// pid of the process locatable + /// + /// @param[in] native_delegate + /// The delegate that will receive messages regarding the + /// inferior. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @param[in] mainloop + /// The mainloop instance with which the process can register + /// callbacks. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @return + /// A NativeProcessProtocol shared pointer if the operation succeeded or + /// an error object if it failed. + //------------------------------------------------------------------ + virtual llvm::Expected<NativeProcessProtocolSP> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const = 0; + }; //------------------------------------------------------------------ /// StartTracing API for starting a tracing instance with the @@ -413,10 +403,10 @@ protected: lldb::pid_t m_pid; std::vector<NativeThreadProtocolSP> m_threads; - lldb::tid_t m_current_thread_id; + lldb::tid_t m_current_thread_id = LLDB_INVALID_THREAD_ID; mutable std::recursive_mutex m_threads_mutex; - lldb::StateType m_state; + lldb::StateType m_state = lldb::eStateInvalid; mutable std::recursive_mutex m_state_mutex; llvm::Optional<WaitStatus> m_exit_status; @@ -427,7 +417,7 @@ protected: NativeWatchpointList m_watchpoint_list; HardwareBreakpointMap m_hw_breakpoints_map; int m_terminal_fd; - uint32_t m_stop_id; + uint32_t m_stop_id = 0; // Set of signal numbers that LLDB directly injects back to inferior // without stopping it. @@ -438,7 +428,8 @@ protected: // then the process should be attached to. When attaching to a process // lldb_private::Host calls should be used to locate the process to attach to, // and then this function should be called. - NativeProcessProtocol(lldb::pid_t pid); + NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, + NativeDelegate &delegate); // ----------------------------------------------------------- // Internal interface for state handling diff --git a/lit/lit.cfg b/lit/lit.cfg index a3d5f9ca7524..8dea61b27169 100644 --- a/lit/lit.cfg +++ b/lit/lit.cfg @@ -95,8 +95,8 @@ if config.test_exec_root is None: lit_config.fatal('No site specific configuration available!') # Get the source and object roots. - llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() - llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() + llvm_src_root = subprocess.check_output(['llvm-config', '--src-root']).strip() + llvm_obj_root = subprocess.check_output(['llvm-config', '--obj-root']).strip() lldb_src_root = os.path.join(llvm_src_root, "tools", "lldb") lldb_obj_root = os.path.join(llvm_obj_root, "tools", "lldb") @@ -132,7 +132,7 @@ if not os.path.exists(config.cxx): if platform.system() in ['Darwin']: try: - out = lit.util.capture(['xcrun', '--show-sdk-path']).strip() + out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip() res = 0 except OSError: res = -1 diff --git a/lldb.xcodeproj/project.pbxproj b/lldb.xcodeproj/project.pbxproj index 8c59fc888412..8353da30bd8e 100644 --- a/lldb.xcodeproj/project.pbxproj +++ b/lldb.xcodeproj/project.pbxproj @@ -868,6 +868,8 @@ 966C6B7C18E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; }; 9694FA711B32AA64005EBB16 /* ABISysV_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9694FA6F1B32AA64005EBB16 /* ABISysV_mips.cpp */; }; 9A0FDEA71E8EF5110086B2F5 /* RegisterContextLinux_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.cpp */; }; + 9A1542F91F0EE48600DEA1D8 /* MockTildeExpressionResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */; }; + 9A1542FA1F0EE48600DEA1D8 /* TestUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; }; 9A1E595C1EB2B141002206A5 /* SBTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */; }; @@ -2815,6 +2817,11 @@ 9A0FDE991E8EF5010086B2F5 /* RegisterInfos_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_arm.h; path = Utility/RegisterInfos_arm.h; sourceTree = "<group>"; }; 9A0FDE9A1E8EF5010086B2F5 /* RegisterInfos_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_arm64.h; path = Utility/RegisterInfos_arm64.h; sourceTree = "<group>"; }; 9A0FDE9B1E8EF5010086B2F5 /* RegisterInfos_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_mips.h; path = Utility/RegisterInfos_mips.h; sourceTree = "<group>"; }; + 9A1542F41F0EE44000DEA1D8 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; + 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MockTildeExpressionResolver.cpp; sourceTree = "<group>"; }; + 9A1542F61F0EE44000DEA1D8 /* MockTildeExpressionResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockTildeExpressionResolver.h; sourceTree = "<group>"; }; + 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestUtilities.cpp; sourceTree = "<group>"; }; + 9A1542F81F0EE44000DEA1D8 /* TestUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestUtilities.h; sourceTree = "<group>"; }; 9A19A6A51163BB7E00E0D453 /* SBValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBValue.h; path = include/lldb/API/SBValue.h; sourceTree = "<group>"; }; 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBValue.cpp; path = source/API/SBValue.cpp; sourceTree = "<group>"; }; 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTrace.cpp; path = source/API/SBTrace.cpp; sourceTree = "<group>"; }; @@ -3305,6 +3312,7 @@ 2321F9421BDD343A00BA9A93 /* Utility */ = { isa = PBXGroup; children = ( + 9A1542F31F0EE44000DEA1D8 /* Helpers */, 2321F9431BDD346100BA9A93 /* CMakeLists.txt */, 23CB15041D66CD9200EDDDE1 /* Inputs */, 2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */, @@ -6216,6 +6224,18 @@ name = "SysV-mips"; sourceTree = "<group>"; }; + 9A1542F31F0EE44000DEA1D8 /* Helpers */ = { + isa = PBXGroup; + children = ( + 9A1542F41F0EE44000DEA1D8 /* CMakeLists.txt */, + 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */, + 9A1542F61F0EE44000DEA1D8 /* MockTildeExpressionResolver.h */, + 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */, + 9A1542F81F0EE44000DEA1D8 /* TestUtilities.h */, + ); + path = Helpers; + sourceTree = "<group>"; + }; AE44FB371BB35A2E0033EB62 /* Go */ = { isa = PBXGroup; children = ( @@ -7003,12 +7023,14 @@ 23CB15371D66DA9300EDDDE1 /* PythonTestSuite.cpp in Sources */, 23E2E5321D903832006F38BB /* BreakpointIDTest.cpp in Sources */, 23CB15381D66DA9300EDDDE1 /* PythonExceptionStateTests.cpp in Sources */, + 9A1542F91F0EE48600DEA1D8 /* MockTildeExpressionResolver.cpp in Sources */, 23CB15391D66DA9300EDDDE1 /* DataExtractorTest.cpp in Sources */, 23CB153A1D66DA9300EDDDE1 /* GDBRemoteClientBaseTest.cpp in Sources */, 23CB153B1D66DA9300EDDDE1 /* SocketTest.cpp in Sources */, 23CB153C1D66DA9300EDDDE1 /* TestArgs.cpp in Sources */, 23CB153D1D66DA9300EDDDE1 /* GDBRemoteCommunicationClientTest.cpp in Sources */, 23CB153E1D66DA9300EDDDE1 /* PythonDataObjectsTests.cpp in Sources */, + 9A1542FA1F0EE48600DEA1D8 /* TestUtilities.cpp in Sources */, 23CB153F1D66DA9300EDDDE1 /* SymbolsTest.cpp in Sources */, AFEC5FD81D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp in Sources */, 23CB15401D66DA9300EDDDE1 /* TestClangASTContext.cpp in Sources */, @@ -8256,7 +8278,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8298,7 +8320,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8340,7 +8362,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8382,7 +8404,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8424,7 +8446,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8466,7 +8488,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8508,7 +8530,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", @@ -8550,7 +8572,7 @@ "$(LLVM_SOURCE_DIR)/tools/clang/include", "$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include", ); - LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; + LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers"; LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)"; OTHER_CFLAGS = ( "-fno-rtti", diff --git a/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py b/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py index 0b9ad0ed6323..5eb7b309c94a 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py +++ b/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py @@ -48,28 +48,8 @@ class ExprCommandThatRestartsTestCase(TestBase): "Restored the zeroth frame correctly") def call_function(self): - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - empty = lldb.SBFileSpec() - breakpoint = target.BreakpointCreateBySourceRegex( - 'Stop here in main.', self.main_source_spec) - self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be at our breakpoint. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - self.thread = threads[0] + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here in main.', self.main_source_spec) # Make sure the SIGCHLD behavior is pass/no-stop/no-notify: return_obj = lldb.SBCommandReturnObject() diff --git a/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py b/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py index e5162609dfa6..f2ec340ac845 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py +++ b/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py @@ -37,28 +37,8 @@ class ExprCommandWithThrowTestCase(TestBase): def call_function(self): """Test calling function that throws.""" - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'I am about to throw.', self.main_source_spec) - self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be at our breakpoint. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - self.thread = threads[0] + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'I am about to throw.', self.main_source_spec) options = lldb.SBExpressionOptions() options.SetUnwindOnError(True) diff --git a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py index a771e7004c94..74991999d926 100644 --- a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py +++ b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py @@ -17,29 +17,14 @@ class ExprCharTestCase(TestBase): self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) - self.exe = os.path.join(os.getcwd(), "a.out") def do_test(self, dictionary=None): """These basic expression commands should work as expected.""" self.build(dictionary=dictionary) - target = self.dbg.CreateTarget(self.exe) - self.assertTrue(target) - - breakpoint = target.BreakpointCreateBySourceRegex( - '// Break here', self.main_source_spec) - self.assertTrue(breakpoint) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process) - - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - self.assertEqual(len(threads), 1) - - frame = threads[0].GetFrameAtIndex(0) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) value = frame.EvaluateExpression("foo(c)") self.assertTrue(value.IsValid()) diff --git a/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py b/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py index 418c5325ad08..4b096149e728 100644 --- a/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py +++ b/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py @@ -37,28 +37,8 @@ class ExprCommandWithFixits(TestBase): def try_expressions(self): """Test calling expressions with errors that can be fixed by the FixIts.""" - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'Stop here to evaluate expressions', self.main_source_spec) - self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be at our breakpoint. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - self.thread = threads[0] + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here to evaluate expressions', self.main_source_spec) options = lldb.SBExpressionOptions() options.SetAutoApplyFixIts(True) diff --git a/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py b/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py index afb497e04b5b..a2d68cffe548 100644 --- a/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py +++ b/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py @@ -32,26 +32,9 @@ class Issue11581TestCase(TestBase): """valobj.AddressOf() should return correct values.""" self.build() - exe = os.path.join(os.getcwd(), "a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'Set breakpoint here.', lldb.SBFileSpec("main.cpp", False)) - - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process, "Created a process.") - self.assertTrue( - process.GetState() == lldb.eStateStopped, - "Stopped it too.") - - thread_list = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - self.assertTrue(len(thread_list) == 1) - thread = thread_list[0] - + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Set breakpoint here.', + lldb.SBFileSpec("main.cpp", False)) self.runCmd("command script import --allow-reload s11588.py") self.runCmd( "type synthetic add --python-class s11588.Issue11581SyntheticProvider StgClosure") diff --git a/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py b/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py index 70b862bf4867..817f6cb3944a 100644 --- a/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py +++ b/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py @@ -30,32 +30,8 @@ class TestMacros(TestBase): src_file_spec = lldb.SBFileSpec(src_file) self.assertTrue(src_file_spec.IsValid(), "Main source file") - # Get the path of the executable - cwd = os.getcwd() - exe_file = "a.out" - exe_path = os.path.join(cwd, exe_file) - - # Load the executable - target = self.dbg.CreateTarget(exe_path) - self.assertTrue(target.IsValid(), VALID_TARGET) - - # Set breakpoints - bp1 = target.BreakpointCreateBySourceRegex("Break here", src_file_spec) - self.assertTrue( - bp1.IsValid() and bp1.GetNumLocations() >= 1, - VALID_BREAKPOINT) - - # Launch the process - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process.IsValid(), PROCESS_IS_VALID) - - # Get the thread of the process - self.assertTrue( - process.GetState() == lldb.eStateStopped, - PROCESS_STOPPED) - thread = lldbutil.get_stopped_thread( - process, lldb.eStopReasonBreakpoint) + (target, process, thread, bp1) = lldbutil.run_to_source_breakpoint( + self, "Break here", src_file_spec) # Get frame for current thread frame = thread.GetSelectedFrame() diff --git a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py index 0d1a17352a3f..b4e9a8bfeab8 100644 --- a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py +++ b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py @@ -37,25 +37,10 @@ class ExprOptionsTestCase(TestBase): # Set debugger into synchronous mode self.dbg.SetAsync(False) - # Create a target by the debugger. - target = self.dbg.CreateTarget(self.exe) - self.assertTrue(target, VALID_TARGET) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, '// breakpoint_in_main', self.main_source_spec) - # Set breakpoints inside main. - breakpoint = target.BreakpointCreateBySourceRegex( - '// breakpoint_in_main', self.main_source_spec) - self.assertTrue(breakpoint) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process, PROCESS_IS_VALID) - - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - self.assertEqual(len(threads), 1) - - frame = threads[0].GetFrameAtIndex(0) + frame = thread.GetFrameAtIndex(0) options = lldb.SBExpressionOptions() # test --language on C++ expression using the SB API's diff --git a/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py b/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py index 7f796971d0ed..f6938b1ea98b 100644 --- a/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py +++ b/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py @@ -31,17 +31,10 @@ class SaveJITObjectsTestCase(TestBase): src_file = "main.c" src_file_spec = lldb.SBFileSpec(src_file) - exe_path = os.path.join(os.getcwd(), "a.out") - target = self.dbg.CreateTarget(exe_path) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "break", src_file_spec) - breakpoint = target.BreakpointCreateBySourceRegex( - "break", src_file_spec) - - process = target.LaunchSimple(None, None, - self.get_process_working_directory()) - - thread = process.GetSelectedThread() - frame = thread.GetSelectedFrame() + frame = thread.frames[0] cleanJITFiles() frame.EvaluateExpression("(void*)malloc(0x1)") diff --git a/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py b/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py index 29c03b1d7ef9..7862477001ea 100644 --- a/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py +++ b/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py @@ -25,36 +25,14 @@ class ExprCommandWithTimeoutsTestCase(TestBase): @expectedFlakeyFreeBSD("llvm.org/pr19605") @expectedFailureAll( oslist=[ - "windows", - "macosx"], + "windows"], bugnumber="llvm.org/pr21765") def test(self): """Test calling std::String member function.""" self.build() - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'stop here in main.', self.main_source_spec) - self.assertTrue(breakpoint, VALID_BREAKPOINT) - self.runCmd("breakpoint list") - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be on self.step_out_of_malloc. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - thread = threads[0] + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, 'stop here in main.', self.main_source_spec) # First set the timeout too short, and make sure we fail. options = lldb.SBExpressionOptions() diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile b/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile new file mode 100644 index 000000000000..5665652329dc --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation -framework AppKit + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py b/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py new file mode 100644 index 000000000000..6a779ecfac5b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py @@ -0,0 +1,57 @@ +""" +Tests basic Main Thread Checker support (detecting a main-thread-only violation). +""" + +import os +import time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbplatformutil import * +import json + + +class MTCSimpleTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test(self): + self.mtc_dylib_path = findMainThreadCheckerDylib() + if self.mtc_dylib_path == "": + self.skipTest("This test requires libMainThreadChecker.dylib.") + + self.build() + self.mtc_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def mtc_tests(self): + # Load the test + exe = os.path.join(os.getcwd(), "a.out") + self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) + + self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path) + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + self.expect("thread info", substrs=['stop reason = -[NSView superview] must be used from main thread only']) + + self.expect( + "thread info -s", + substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"]) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation) + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "MainThreadChecker") + self.assertEqual(data["api_name"], "-[NSView superview]") + self.assertEqual(data["class_name"], "NSView") + self.assertEqual(data["selector"], "superview") + self.assertEqual(data["description"], "-[NSView superview] must be used from main thread only") diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m b/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m new file mode 100644 index 000000000000..651347cf74ee --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m @@ -0,0 +1,15 @@ +#import <Foundation/Foundation.h> +#import <AppKit/AppKit.h> + +int main() { + NSView *view = [[NSView alloc] init]; + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + [NSThread detachNewThreadWithBlock:^{ + @autoreleasepool { + [view superview]; + } + dispatch_group_leave(g); + }]; + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); +} diff --git a/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py b/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py index cf435a4aae91..1750bd31b3df 100644 --- a/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py +++ b/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py @@ -31,8 +31,6 @@ class ReturnValueTestCase(TestBase): "<=", "3.6"], archs=["i386"]) - @expectedFailureAll(compiler="clang", compiler_version=["<=", "5.0.300080"], - triple='.*-android', archs=["i386"]) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @add_test_categories(['pyapi']) def test_with_python(self): diff --git a/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py b/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py index efadea51f669..79175562fe7a 100644 --- a/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py +++ b/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py @@ -16,6 +16,7 @@ from lldbsuite.test import lldbutil class RaiseTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True def test_sigstop(self): self.build() @@ -29,6 +30,10 @@ class RaiseTestCase(TestBase): self.build() self.signal_test('SIGRTMIN', True) + def test_sigtrap(self): + self.build() + self.signal_test('SIGTRAP', True) + def launch(self, target, signal): # launch the process, do not stop at entry point. process = target.LaunchSimple( diff --git a/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c b/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c index 8827174e758e..4203fe5d4c89 100644 --- a/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c +++ b/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c @@ -10,6 +10,11 @@ void handler(int signo) int main (int argc, char *argv[]) { + if (signal(SIGTRAP, handler) == SIG_ERR) + { + perror("signal(SIGTRAP)"); + return 1; + } #ifndef __APPLE__ // Real time signals not supported on apple platforms. if (signal(SIGRTMIN, handler) == SIG_ERR) @@ -27,6 +32,8 @@ int main (int argc, char *argv[]) if (strcmp(argv[1], "SIGSTOP") == 0) raise(SIGSTOP); + else if (strcmp(argv[1], "SIGTRAP") == 0) + raise(SIGTRAP); #ifndef __APPLE__ else if (strcmp(argv[1], "SIGRTMIN") == 0) raise(SIGRTMIN); diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile new file mode 100644 index 000000000000..6e7d19b6f48c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=undefined -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py new file mode 100644 index 000000000000..a5e5f572a979 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py @@ -0,0 +1,49 @@ +""" +Test that hitting a UBSan issue while running user expression doesn't break the evaluation. +""" + +import os +import time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class UbsanUserExpressionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessUndefinedBehaviorSanitizer + def test(self): + self.build() + self.ubsan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_breakpoint = line_number('main.c', '// breakpoint line') + + def ubsan_tests(self): + # Load the test + exe = os.path.join(os.getcwd(), "a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) + + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect("p foo()", substrs=["(int) $0 = 42"]) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c new file mode 100644 index 000000000000..4786aaa89b27 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c @@ -0,0 +1,9 @@ +int foo() { + int data[4]; + int x = *(int *)(((char *)&data[0]) + 2); + return 42; +} + +int main() { + return 0; // breakpoint line +} diff --git a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py index 8e158c3e82d4..9571e259629f 100644 --- a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py +++ b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py @@ -20,6 +20,7 @@ class TestGoASTContext(TestBase): @skipIfRemote # Not remote test suit ready @no_debug_info_test @skipUnlessGoInstalled + @expectedFailureAll(bugnumber="llvm.org/pr33643") def test_with_dsym_and_python_api(self): """Test GoASTContext dwarf parsing.""" self.buildGo() diff --git a/packages/Python/lldbsuite/test/lldbplatformutil.py b/packages/Python/lldbsuite/test/lldbplatformutil.py index 89ce1d468bd0..4f45643241ed 100644 --- a/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -8,6 +8,7 @@ import itertools import re import subprocess import sys +import os # Third-party modules import six @@ -140,6 +141,19 @@ def platformIsDarwin(): return getPlatform() in getDarwinOSTriples() +def findMainThreadCheckerDylib(): + if not platformIsDarwin(): + return "" + + with os.popen('xcode-select -p') as output: + xcode_developer_path = output.read().strip() + mtc_dylib_path = '%s/usr/lib/libMainThreadChecker.dylib' % xcode_developer_path + if os.path.isfile(mtc_dylib_path): + return mtc_dylib_path + + return "" + + class _PlatformContext(object): """Value object class which contains platform-specific options.""" diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py index 7732dbe6dff3..58a1ead1ea0b 100644 --- a/packages/Python/lldbsuite/test/lldbutil.py +++ b/packages/Python/lldbsuite/test/lldbutil.py @@ -725,6 +725,47 @@ def get_crashed_threads(test, process): threads.append(thread) return threads +def run_to_source_breakpoint(test, bkpt_pattern, source_spec, launch_info = None, exe_name = "a.out", in_cwd = True): + """Start up a target, using exe_name as the executable, and run it to + a breakpoint set by source regex bkpt_pattern. + If you want to pass in launch arguments or environment variables, you can optionally pass in + an SBLaunchInfo. If you do that, remember to set the working directory as well. + If your executable isn't called a.out, you can pass that in. And if your executable isn't + in the CWD, pass in the absolute path to the executable in exe_name, and set in_cwd to False. + If the target isn't valid, the breakpoint isn't found, or hit, the + function will cause a testsuite failure. + If successful it returns a tuple with the target process and thread that hit the breakpoint.""" + + if in_cwd: + exe = os.path.join(os.getcwd(), exe_name) + + # Create the target + target = test.dbg.CreateTarget(exe) + test.assertTrue(target, "Target: %s is not valid."%(exe_name)) + + # Set the breakpoints + breakpoint = target.BreakpointCreateBySourceRegex( + bkpt_pattern, source_spec) + test.assertTrue(breakpoint.GetNumLocations() > 0, + 'No locations found for source breakpoint: "%s"'%(bkpt_pattern)) + + # Launch the process, and do not stop at the entry point. + if not launch_info: + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetWorkingDirectory(test.get_process_working_directory()) + + error = lldb.SBError() + process = target.Launch(launch_info, error) + + test.assertTrue(process, "Could not create a valid process for %s: %s"%(exe_name, error.GetCString())) + + # Frame #0 should be at our breakpoint. + threads = get_threads_stopped_at_breakpoint( + process, breakpoint) + + test.assertTrue(len(threads) == 1, "Expected 1 thread to stop at breakpoint, %d did."%(len(threads))) + thread = threads[0] + return (target, process, thread, breakpoint) def continue_to_breakpoint(process, bkpt): """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" diff --git a/packages/Python/lldbsuite/test/make/Android.rules b/packages/Python/lldbsuite/test/make/Android.rules index 0a725494d354..058401f425ad 100644 --- a/packages/Python/lldbsuite/test/make/Android.rules +++ b/packages/Python/lldbsuite/test/make/Android.rules @@ -90,7 +90,3 @@ else ARCH_LDFLAGS += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(STL_ARCH)/libgnustl_static.a endif - -ifeq "$(ARCH)" "i386" - ARCH_CFLAGS += -mstackrealign -endif diff --git a/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py b/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py index bb34727ff81b..9a1748bbabb5 100644 --- a/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py +++ b/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py @@ -25,6 +25,7 @@ class RenameThisSampleTestTestCase(TestBase): def test_sample_rename_this(self): """There can be many tests in a test case - describe this test here.""" self.build() + self.main_source_file = lldb.SBFileSpec("main.c") self.sample_test() def setUp(self): @@ -33,40 +34,15 @@ class RenameThisSampleTestTestCase(TestBase): def sample_test(self): """You might use the test implementation in several ways, say so here.""" - exe = os.path.join(os.getcwd(), "a.out") - # Create a target by the debugger. - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) + # This function starts a process, "a.out" by default, sets a source + # breakpoint, runs to it, and returns the thread, process & target. + # It optionally takes an SBLaunchOption argument if you want to pass + # arguments or environment variables. + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) - # Now create a breakpoint in main.c at the source matching - # "Set a breakpoint here" - breakpoint = target.BreakpointCreateBySourceRegex( - "Set a breakpoint here", lldb.SBFileSpec("main.c")) - self.assertTrue(breakpoint and - breakpoint.GetNumLocations() >= 1, - VALID_BREAKPOINT) - - error = lldb.SBError() - # This is the launch info. If you want to launch with arguments or - # environment variables, add them using SetArguments or - # SetEnvironmentEntries - - launch_info = lldb.SBLaunchInfo(None) - process = target.Launch(launch_info, error) - self.assertTrue(process, PROCESS_IS_VALID) - - # Did we hit our breakpoint? - from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint - threads = get_threads_stopped_at_breakpoint(process, breakpoint) - self.assertTrue( - len(threads) == 1, - "There should be a thread stopped at our breakpoint") - - # The hit count for the breakpoint should be 1. - self.assertTrue(breakpoint.GetHitCount() == 1) - - frame = threads[0].GetFrameAtIndex(0) + frame = thread.GetFrameAtIndex(0) test_var = frame.FindVariable("test_var") self.assertTrue(test_var.GetError().Success(), "Failed to fetch test_var") test_value = test_var.GetValueAsUnsigned() diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index 687187b26ccd..6a933df43e14 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -161,9 +161,9 @@ public: // List the common thread ID's const std::vector<uint32_t> &thread_index_ids = stack.GetUniqueThreadIndexIDs(); - strm.Printf("%lu thread(s) ", thread_index_ids.size()); + strm.Format("{0} thread(s) ", thread_index_ids.size()); for (const uint32_t &thread_index_id : thread_index_ids) { - strm.Printf("#%u ", thread_index_id); + strm.Format("#{0} ", thread_index_id); } strm.EOL(); @@ -209,7 +209,7 @@ protected: Process *process = m_exe_ctx.GetProcessPtr(); Thread *thread = process->GetThreadList().FindThreadByID(tid).get(); if (thread == nullptr) { - result.AppendErrorWithFormat("Failed to process thread# %llu.\n", tid); + result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid); result.SetStatus(eReturnStatusFailed); return false; } diff --git a/source/Core/DumpDataExtractor.cpp b/source/Core/DumpDataExtractor.cpp index 2b7abd60f8bc..c2a9115c3068 100644 --- a/source/Core/DumpDataExtractor.cpp +++ b/source/Core/DumpDataExtractor.cpp @@ -154,7 +154,8 @@ lldb::offset_t lldb_private::DumpDataExtractor( target_sp = exe_scope->CalculateTarget(); if (target_sp) { DisassemblerSP disassembler_sp(Disassembler::FindPlugin( - target_sp->GetArchitecture(), nullptr, nullptr)); + target_sp->GetArchitecture(), + target_sp->GetDisassemblyFlavor(), nullptr)); if (disassembler_sp) { lldb::addr_t addr = base_addr + start_offset; lldb_private::Address so_addr; diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index 3de93ebc220b..90a4462c6ca9 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -24,10 +24,12 @@ #endif #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() #include "lldb/Host/Config.h" +#include "lldb/Host/Host.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -133,9 +135,8 @@ FILE *File::GetStream() { m_should_close_fd = true; } - do { - m_stream = ::fdopen(m_descriptor, mode); - } while (m_stream == NULL && errno == EINTR); + m_stream = + llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode); // If we got a stream, then we own the stream and should no // longer own the descriptor because fclose() will close it for us @@ -157,6 +158,19 @@ void File::SetStream(FILE *fh, bool transfer_ownership) { m_own_stream = transfer_ownership; } +static int DoOpen(const char *path, int flags, int mode) { +#ifdef _MSC_VER + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) + return -1; + int result; + ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode); + return result; +#else + return ::open(path, flags, mode); +#endif +} + Status File::Open(const char *path, uint32_t options, uint32_t permissions) { Status error; if (IsValid()) @@ -222,20 +236,7 @@ Status File::Open(const char *path, uint32_t options, uint32_t permissions) { mode |= S_IXOTH; } - do { -#ifdef _MSC_VER - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) { - m_descriptor = -1; - error.SetErrorString("Error converting path to UTF-16"); - return error; - } - ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); -#else - m_descriptor = ::open(path, oflag, mode); -#endif - } while (m_descriptor < 0 && errno == EINTR); - + m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode); if (!DescriptorIsValid()) error.SetErrorToErrno(); else { @@ -421,12 +422,7 @@ off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { Status File::Flush() { Status error; if (StreamIsValid()) { - int err = 0; - do { - err = ::fflush(m_stream); - } while (err == EOF && errno == EINTR); - - if (err == EOF) + if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) error.SetErrorToErrno(); } else if (!DescriptorIsValid()) { error.SetErrorString("invalid file handle"); @@ -442,12 +438,7 @@ Status File::Sync() { if (err == 0) error.SetErrorToGenericError(); #else - int err = 0; - do { - err = ::fsync(m_descriptor); - } while (err == -1 && errno == EINTR); - - if (err == -1) + if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1) error.SetErrorToErrno(); #endif } else { @@ -497,10 +488,7 @@ Status File::Read(void *buf, size_t &num_bytes) { ssize_t bytes_read = -1; if (DescriptorIsValid()) { - do { - bytes_read = ::read(m_descriptor, buf, num_bytes); - } while (bytes_read < 0 && errno == EINTR); - + bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes); if (bytes_read == -1) { error.SetErrorToErrno(); num_bytes = 0; @@ -559,10 +547,8 @@ Status File::Write(const void *buf, size_t &num_bytes) { ssize_t bytes_written = -1; if (DescriptorIsValid()) { - do { - bytes_written = ::write(m_descriptor, buf, num_bytes); - } while (bytes_written < 0 && errno == EINTR); - + bytes_written = + llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes); if (bytes_written == -1) { error.SetErrorToErrno(); num_bytes = 0; @@ -624,11 +610,8 @@ Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { #ifndef _WIN32 int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { - ssize_t bytes_read = -1; - do { - bytes_read = ::pread(fd, buf, num_bytes, offset); - } while (bytes_read < 0 && errno == EINTR); - + ssize_t bytes_read = + llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset); if (bytes_read < 0) { num_bytes = 0; error.SetErrorToErrno(); @@ -730,11 +713,8 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { #ifndef _WIN32 - ssize_t bytes_written = -1; - do { - bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); - } while (bytes_written < 0 && errno == EINTR); - + ssize_t bytes_written = + llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset); if (bytes_written < 0) { num_bytes = 0; error.SetErrorToErrno(); diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp index 7de6f7fa865d..c0c4471e735f 100644 --- a/source/Host/common/MainLoop.cpp +++ b/source/Host/common/MainLoop.cpp @@ -193,10 +193,16 @@ Status MainLoop::RunImpl::Poll() { void MainLoop::RunImpl::ProcessEvents() { #ifdef FORCE_PSELECT - for (const auto &fd : loop.m_read_fds) { - if (!FD_ISSET(fd.first, &read_fd_set)) - continue; - IOObject::WaitableHandle handle = fd.first; + // Collect first all readable file descriptors into a separate vector and then + // iterate over it to invoke callbacks. Iterating directly over + // loop.m_read_fds is not possible because the callbacks can modify the + // container which could invalidate the iterator. + std::vector<IOObject::WaitableHandle> fds; + for (const auto &fd : loop.m_read_fds) + if (FD_ISSET(fd.first, &read_fd_set)) + fds.push_back(fd.first); + + for (const auto &handle : fds) { #else for (const auto &fd : read_fds) { if ((fd.revents & POLLIN) == 0) @@ -209,13 +215,16 @@ void MainLoop::RunImpl::ProcessEvents() { loop.ProcessReadObject(handle); } - for (const auto &entry : loop.m_signals) { + std::vector<int> signals; + for (const auto &entry : loop.m_signals) + if (g_signal_flags[entry.first] != 0) + signals.push_back(entry.first); + + for (const auto &signal : signals) { if (loop.m_terminate_request) return; - if (g_signal_flags[entry.first] == 0) - continue; // No signal - g_signal_flags[entry.first] = 0; - loop.ProcessSignal(entry.first); + g_signal_flags[signal] = 0; + loop.ProcessSignal(signal); } } #endif diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 341c301dc9c5..b5b6e9d8b923 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -29,11 +29,13 @@ using namespace lldb_private; // NativeProcessProtocol Members // ----------------------------------------------------------------------------- -NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid) - : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID), - m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(), - m_delegates_mutex(), m_delegates(), m_breakpoint_list(), - m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {} +NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, + NativeDelegate &delegate) + : m_pid(pid), m_terminal_fd(terminal_fd) { + bool registered = RegisterNativeDelegate(delegate); + assert(registered); + (void)registered; +} lldb_private::Status NativeProcessProtocol::Interrupt() { Status error; @@ -488,23 +490,4 @@ Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, "failed to retrieve a valid architecture from the exe module"); } -#if !defined(__linux__) && !defined(__NetBSD__) -// These need to be implemented to support lldb-gdb-server on a given platform. -// Stubs are -// provided to make the rest of the code link on non-supported platforms. - -Status NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) { - llvm_unreachable("Platform has no NativeProcessProtocol support"); -} - -Status NativeProcessProtocol::Attach(lldb::pid_t pid, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) { - llvm_unreachable("Platform has no NativeProcessProtocol support"); -} - -#endif +NativeProcessProtocol::Factory::~Factory() = default; diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 440ae5d9027f..41150fa7fd74 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -201,7 +201,7 @@ const SocketAddress &SocketAddress:: operator=(const struct addrinfo *addr_info) { Clear(); if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && - addr_info->ai_addrlen <= sizeof m_socket_addr) { + size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) { ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); } return *this; diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm index bbf70cd4c4b3..75624ef21f43 100644 --- a/source/Host/macosx/Host.mm +++ b/source/Host/macosx/Host.mm @@ -74,6 +74,7 @@ #include "lldb/Utility/StructuredData.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Errno.h" #include "cfcpp/CFCBundle.h" #include "cfcpp/CFCMutableArray.h" @@ -1663,10 +1664,7 @@ HostThread Host::StartMonitoringChildProcess( int wait_pid = 0; bool cancel = false; bool exited = false; - do { - wait_pid = ::waitpid(pid, &status, 0); - } while (wait_pid < 0 && errno == EINTR); - + wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, 0); if (wait_pid >= 0) { int signal = 0; int exit_status = 0; diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 6b0f069c35a9..105ef0f23d46 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -245,11 +245,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, } else if ((addr = GetURLAddress(path, FILE_SCHEME))) { std::string addr_str = addr->str(); // file:///PATH - int fd = -1; - do { - fd = ::open(addr_str.c_str(), O_RDWR); - } while (fd == -1 && errno == EINTR); - + int fd = llvm::sys::RetryAfterSignal(-1, ::open, addr_str.c_str(), O_RDWR); if (fd == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); @@ -620,20 +616,17 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout, if (select_helper.FDIsSetRead(pipe_fd)) { // There is an interrupt or exit command in the command pipe // Read the data from that pipe: - char buffer[1]; - - ssize_t bytes_read; - - do { - bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); - } while (bytes_read < 0 && errno == EINTR); + char c; - switch (buffer[0]) { + ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1); + assert(bytes_read == 1); + (void)bytes_read; + switch (c) { case 'q': if (log) log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " "got data: %c from the command channel.", - static_cast<void *>(this), buffer[0]); + static_cast<void *>(this), c); return eConnectionStatusEndOfFile; case 'i': // Interrupt the current read diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp index d385b78e0ec4..5dbb3bb4ef7e 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp @@ -63,10 +63,10 @@ void AuxVector::ParseAuxv(DataExtractor &data) { if (!ParseAuxvEntry(data, entry, &offset, byte_size)) break; - if (entry.type == AT_NULL) + if (entry.type == AUXV_AT_NULL) break; - if (entry.type == AT_IGNORE) + if (entry.type == AUXV_AT_IGNORE) continue; m_auxv.push_back(entry); @@ -110,43 +110,43 @@ void AuxVector::DumpToLog(Log *log) const { const char *AuxVector::GetEntryName(EntryType type) { const char *name = "AT_???"; -#define ENTRY_NAME(_type) \ - _type: \ - name = #_type +#define ENTRY_NAME(_type) \ + _type: \ + name = #_type + 5 switch (type) { - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - case ENTRY_NAME(AT_PLATFORM); break; - case ENTRY_NAME(AT_HWCAP); break; - case ENTRY_NAME(AT_FPUCW); break; - case ENTRY_NAME(AT_DCACHEBSIZE); break; - case ENTRY_NAME(AT_ICACHEBSIZE); break; - case ENTRY_NAME(AT_UCACHEBSIZE); break; - case ENTRY_NAME(AT_IGNOREPPC); break; - case ENTRY_NAME(AT_SECURE); break; - case ENTRY_NAME(AT_BASE_PLATFORM); break; - case ENTRY_NAME(AT_RANDOM); break; - case ENTRY_NAME(AT_EXECFN); break; - case ENTRY_NAME(AT_SYSINFO); break; - case ENTRY_NAME(AT_SYSINFO_EHDR); break; - case ENTRY_NAME(AT_L1I_CACHESHAPE); break; - case ENTRY_NAME(AT_L1D_CACHESHAPE); break; - case ENTRY_NAME(AT_L2_CACHESHAPE); break; - case ENTRY_NAME(AT_L3_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_NULL); break; + case ENTRY_NAME(AUXV_AT_IGNORE); break; + case ENTRY_NAME(AUXV_AT_EXECFD); break; + case ENTRY_NAME(AUXV_AT_PHDR); break; + case ENTRY_NAME(AUXV_AT_PHENT); break; + case ENTRY_NAME(AUXV_AT_PHNUM); break; + case ENTRY_NAME(AUXV_AT_PAGESZ); break; + case ENTRY_NAME(AUXV_AT_BASE); break; + case ENTRY_NAME(AUXV_AT_FLAGS); break; + case ENTRY_NAME(AUXV_AT_ENTRY); break; + case ENTRY_NAME(AUXV_AT_NOTELF); break; + case ENTRY_NAME(AUXV_AT_UID); break; + case ENTRY_NAME(AUXV_AT_EUID); break; + case ENTRY_NAME(AUXV_AT_GID); break; + case ENTRY_NAME(AUXV_AT_EGID); break; + case ENTRY_NAME(AUXV_AT_CLKTCK); break; + case ENTRY_NAME(AUXV_AT_PLATFORM); break; + case ENTRY_NAME(AUXV_AT_HWCAP); break; + case ENTRY_NAME(AUXV_AT_FPUCW); break; + case ENTRY_NAME(AUXV_AT_DCACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_ICACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_UCACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_IGNOREPPC); break; + case ENTRY_NAME(AUXV_AT_SECURE); break; + case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break; + case ENTRY_NAME(AUXV_AT_RANDOM); break; + case ENTRY_NAME(AUXV_AT_EXECFN); break; + case ENTRY_NAME(AUXV_AT_SYSINFO); break; + case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break; + case ENTRY_NAME(AUXV_AT_L1I_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L1D_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L2_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L3_CACHESHAPE); break; } #undef ENTRY_NAME diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h index 9c3e1b002a24..cf9da0808357 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h @@ -42,41 +42,42 @@ public: /// Constants describing the type of entry. /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information. + /// Added AUXV prefix to avoid potential conflicts with system-defined macros enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). - AT_PLATFORM = 15, ///< String identifying platform. - AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. - AT_FPUCW = 18, ///< Used FPU control word. - AT_DCACHEBSIZE = 19, ///< Data cache block size. - AT_ICACHEBSIZE = 20, ///< Instruction cache block size. - AT_UCACHEBSIZE = 21, ///< Unified cache block size. - AT_IGNOREPPC = 22, ///< Entry should be ignored. - AT_SECURE = 23, ///< Boolean, was exec setuid-like? - AT_BASE_PLATFORM = 24, ///< String identifying real platforms. - AT_RANDOM = 25, ///< Address of 16 random bytes. - AT_EXECFN = 31, ///< Filename of executable. - AT_SYSINFO = 32, ///< Pointer to the global system page used for system - ///calls and other nice things. - AT_SYSINFO_EHDR = 33, - AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. - AT_L1D_CACHESHAPE = 35, - AT_L2_CACHESHAPE = 36, - AT_L3_CACHESHAPE = 37, + AUXV_AT_NULL = 0, ///< End of auxv. + AUXV_AT_IGNORE = 1, ///< Ignore entry. + AUXV_AT_EXECFD = 2, ///< File descriptor of program. + AUXV_AT_PHDR = 3, ///< Program headers. + AUXV_AT_PHENT = 4, ///< Size of program header. + AUXV_AT_PHNUM = 5, ///< Number of program headers. + AUXV_AT_PAGESZ = 6, ///< Page size. + AUXV_AT_BASE = 7, ///< Interpreter base address. + AUXV_AT_FLAGS = 8, ///< Flags. + AUXV_AT_ENTRY = 9, ///< Program entry point. + AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF. + AUXV_AT_UID = 11, ///< UID. + AUXV_AT_EUID = 12, ///< Effective UID. + AUXV_AT_GID = 13, ///< GID. + AUXV_AT_EGID = 14, ///< Effective GID. + AUXV_AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). + AUXV_AT_PLATFORM = 15, ///< String identifying platform. + AUXV_AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. + AUXV_AT_FPUCW = 18, ///< Used FPU control word. + AUXV_AT_DCACHEBSIZE = 19, ///< Data cache block size. + AUXV_AT_ICACHEBSIZE = 20, ///< Instruction cache block size. + AUXV_AT_UCACHEBSIZE = 21, ///< Unified cache block size. + AUXV_AT_IGNOREPPC = 22, ///< Entry should be ignored. + AUXV_AT_SECURE = 23, ///< Boolean, was exec setuid-like? + AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms. + AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes. + AUXV_AT_EXECFN = 31, ///< Filename of executable. + AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system + ///calls and other nice things. + AUXV_AT_SYSINFO_EHDR = 33, + AUXV_AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. + AUXV_AT_L1D_CACHESHAPE = 35, + AUXV_AT_L2_CACHESHAPE = 36, + AUXV_AT_L3_CACHESHAPE = 37, }; private: diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 0092535648bd..a7afeb6d68c3 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -576,7 +576,7 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { } void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() { - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR); if (I != m_auxv->end()) m_vdso_base = I->value; @@ -589,7 +589,7 @@ addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { if (m_auxv.get() == NULL) return LLDB_INVALID_ADDRESS; - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_ENTRY); if (I == m_auxv->end()) return LLDB_INVALID_ADDRESS; diff --git a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp index af242d786a5f..9a6e39be0bfd 100644 --- a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp @@ -247,12 +247,16 @@ bool AddressSanitizerRuntime::NotifyBreakpointHit( AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime *>(baton); + ProcessSP process_sp = instance->GetProcessSP(); + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(); std::string description; if (report) { description = instance->FormatDescription(report); } - ProcessSP process_sp = instance->GetProcessSP(); // Make sure this is the right process if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); diff --git a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp index 3c22b81df7a4..eb238419ab18 100644 --- a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp @@ -141,7 +141,7 @@ MainThreadCheckerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { d->AddStringItem("class_name", className); d->AddStringItem("selector", selector); d->AddStringItem("description", - apiName + " must be called from main thread only"); + apiName + " must be used from main thread only"); d->AddIntegerItem("tid", thread_sp->GetIndexID()); d->AddItem("trace", trace_sp); return dict_sp; @@ -163,6 +163,9 @@ bool MainThreadCheckerRuntime::NotifyBreakpointHit( process_sp != context->exe_ctx_ref.GetProcessSP()) return false; + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp index f60df0463346..cf9ba60c7b60 100644 --- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -803,6 +803,11 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( ThreadSanitizerRuntime *const instance = static_cast<ThreadSanitizerRuntime *>(baton); + ProcessSP process_sp = instance->GetProcessSP(); + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); std::string stop_reason_description; @@ -851,7 +856,6 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( all_addresses_are_same); } - ProcessSP process_sp = instance->GetProcessSP(); // Make sure this is the right process if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); diff --git a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp index 023af84179aa..28c28e41ef44 100644 --- a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp @@ -217,6 +217,9 @@ bool UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit( process_sp != context->exe_ctx_ref.GetProcessSP()) return false; + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp index 2ba005e02ad4..8f4997533212 100644 --- a/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/source/Plugins/Language/ObjC/Cocoa.cpp @@ -543,6 +543,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( } uint64_t value = 0; + bool success = false; switch (type_code) { case TypeCodes::sint8: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, @@ -550,6 +551,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (error.Fail()) return false; NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint16: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, @@ -558,6 +560,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( return false; NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint32: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, @@ -565,6 +568,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (error.Fail()) return false; NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint64: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, @@ -572,6 +576,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (error.Fail()) return false; NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); + success = true; break; case TypeCodes::f32: { @@ -582,6 +587,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( float flt_value = 0.0f; memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int)); NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); + success = true; break; } case TypeCodes::f64: @@ -593,6 +599,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( double dbl_value = 0.0; memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng)); NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); + success = true; break; } case TypeCodes::sint128: // internally, this is the same @@ -608,12 +615,11 @@ bool lldb_private::formatters::NSNumberSummaryProvider( return false; llvm::APInt i128_value(128, words); NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage()); + success = true; break; } - default: - return false; } - return true; + return success; } } diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp index d896a9f99e63..0f37da60d5d6 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -366,13 +366,17 @@ bool PlatformAndroid::GetRemoteOSVersion() { return m_major_os_version != 0; } -const char *PlatformAndroid::GetLibdlFunctionDeclarations() const { - return R"( +llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { + // Older platform versions have the dl function symbols mangled + if (GetSdkVersion() < 26) + return R"( extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); extern "C" int dlclose(void*) asm("__dl_dlclose"); extern "C" char* dlerror(void) asm("__dl_dlerror"); )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(); } AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) { diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h index 8fb4cc71a69f..638dba973369 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/source/Plugins/Platform/Android/PlatformAndroid.h @@ -76,7 +76,7 @@ protected: Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override; - const char *GetLibdlFunctionDeclarations() const override; + llvm::StringRef GetLibdlFunctionDeclarations() override; private: AdbClient::SyncService *GetSyncService(Status &error); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index f4cf22ad7583..013c33def13b 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -884,7 +884,7 @@ void PlatformPOSIX::CalculateTrapHandlerSymbolNames() { Status PlatformPOSIX::EvaluateLibdlExpression( lldb_private::Process *process, const char *expr_cstr, - const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { + llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { DynamicLoader *loader = process->GetDynamicLoader(); if (loader) { Status error = loader->CanLoadImage(); @@ -944,7 +944,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, the_result; )", path); - const char *prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(); lldb::ValueObjectSP result_valobj_sp; error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -992,7 +992,7 @@ Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, StreamString expr; expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); - const char *prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(); lldb::ValueObjectSP result_valobj_sp; Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -1024,7 +1024,7 @@ lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url, error); } -const char *PlatformPOSIX::GetLibdlFunctionDeclarations() const { +llvm::StringRef PlatformPOSIX::GetLibdlFunctionDeclarations() { return R"( extern "C" void* dlopen(const char*, int); extern "C" void* dlsym(void*, const char*); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 742702b07b88..ebc36c2461db 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -198,10 +198,10 @@ protected: lldb_private::Status EvaluateLibdlExpression(lldb_private::Process *process, const char *expr_cstr, - const char *expr_prefix, + llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp); - virtual const char *GetLibdlFunctionDeclarations() const; + virtual llvm::StringRef GetLibdlFunctionDeclarations(); private: DISALLOW_COPY_AND_ASSIGN(PlatformPOSIX); diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 10dd14753914..a4f5f02dde62 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -746,15 +746,9 @@ ProcessMonitor::ProcessMonitor( if (!error.Success()) return; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) { - if (errno == EINTR) - goto WAIT_AGAIN; - else { - error.SetErrorToErrno(); - return; - } + if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { + error.SetErrorToErrno(); + return; } // Check that the launch was a success. @@ -790,15 +784,9 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, if (!error.Success()) return; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) { - if (errno == EINTR) - goto WAIT_AGAIN; - else { - error.SetErrorToErrno(); - return; - } + if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { + error.SetErrorToErrno(); + return; } // Check that the attach was a success. diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 8e378802de9c..d988ee93a2bc 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -214,207 +214,122 @@ static Status EnsureFDFlags(int fd, int flags) { // Public Static Methods // ----------------------------------------------------------------------------- -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { +llvm::Expected<NativeProcessProtocolSP> +NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - Status error; + MaybeLogLaunchInfo(launch_info); - // Verify the working directory is valid if one was specified. - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && (!working_dir.ResolvePath() || - !llvm::sys::fs::is_directory(working_dir.GetPath()))) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); } - // Create the NativeProcessLinux in launch mode. - native_process_sp.reset(new NativeProcessLinux()); - - if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { - native_process_sp.reset(); - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error<StringError>("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); } + LLDB_LOG(log, "inferior started, now in stopped state"); - error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp) - ->LaunchInferior(mainloop, launch_info); + ArchSpec arch; + if ((status = ResolveProcessArchitecture(pid, arch)).Fail()) + return status.ToError(); - if (error.Fail()) { - native_process_sp.reset(); - LLDB_LOG(log, "failed to launch process: {0}", error); - return error; - } + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + arch.GetArchitectureName()); - launch_info.SetProcessID(native_process_sp->GetID()); + status = SetDefaultPtraceOpts(pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to set default ptrace options: {0}", status); + return status.ToError(); + } - return error; + std::shared_ptr<NativeProcessLinux> process_sp(new NativeProcessLinux( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + arch, mainloop)); + process_sp->InitializeThreads({pid}); + return process_sp; } -Status NativeProcessProtocol::Attach( +llvm::Expected<NativeProcessProtocolSP> NativeProcessLinux::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - return error; + ArchSpec arch; + Status status = ResolveProcessArchitecture(pid, arch); + if (!status.Success()) + return status.ToError(); - std::shared_ptr<NativeProcessLinux> native_process_linux_sp( - new NativeProcessLinux()); + auto tids_or = NativeProcessLinux::Attach(pid); + if (!tids_or) + return tids_or.takeError(); - if (!native_process_linux_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } - - native_process_linux_sp->AttachToInferior(mainloop, pid, error); - if (!error.Success()) - return error; - - native_process_sp = native_process_linux_sp; - return error; + std::shared_ptr<NativeProcessLinux> process_sp( + new NativeProcessLinux(pid, -1, native_delegate, arch, mainloop)); + process_sp->InitializeThreads(*tids_or); + return process_sp; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessLinux::NativeProcessLinux() - : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), - m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache(), - m_pending_notification_tid(LLDB_INVALID_THREAD_ID), - m_pt_proces_trace_id(LLDB_INVALID_UID) {} - -void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); +NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + Status status; m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - m_arch.GetArchitectureName()); - m_pid = pid; - SetState(eStateAttaching); - - Attach(pid, error); + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); } -Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, - ProcessLaunchInfo &launch_info) { - Status error; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; - - SetState(eStateLaunching); - - MaybeLogLaunchInfo(launch_info); - - ::pid_t pid = - ProcessLauncherPosixFork().LaunchProcess(launch_info, error).GetProcessId(); - if (error.Fail()) - return error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) { - error.SetErrorToErrno(); - LLDB_LOG(log, "waitpid for inferior failed with %s", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && - "Could not sync with inferior process."); - - LLDB_LOG(log, "inferior started, now in stopped state"); - error = SetDefaultPtraceOpts(pid); - if (error.Fail()) { - LLDB_LOG(log, "failed to set default ptrace options: {0}", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - - // Release the master terminal descriptor and pass it off to the - // NativeProcessLinux instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); - - if (m_terminal_fd != -1) { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) { - LLDB_LOG(log, - "inferior EnsureFDFlags failed for ensuring terminal " - "O_NONBLOCK setting: {0}", - error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } +void NativeProcessLinux::InitializeThreads(llvm::ArrayRef<::pid_t> tids) { + for (const auto &tid : tids) { + NativeThreadLinuxSP thread_sp = AddThread(tid); + assert(thread_sp && "AddThread() returned a nullptr thread"); + thread_sp->SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(*thread_sp); } - LLDB_LOG(log, "adding pid = {0}", pid); - ResolveProcessArchitecture(m_pid, m_arch); - NativeThreadLinuxSP thread_sp = AddThread(pid); - assert(thread_sp && "AddThread() returned a nullptr thread"); - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - // Let our process instance know the thread has stopped. - SetCurrentThreadID(thread_sp->GetID()); - SetState(StateType::eStateStopped); + SetCurrentThreadID(tids[0]); + SetState(StateType::eStateStopped, false); - if (error.Fail()) - LLDB_LOG(log, "inferior launching failed {0}", error); - return error; + // Proccess any signals we received before installing our handler + SigchldHandler(); } -::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Status &error) { +llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Status status; // Use a map to keep track of the threads which we have attached/need to // attach. Host::TidMap tids_to_attach; - if (pid <= 1) { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } - while (Host::FindProcessThreads(pid, tids_to_attach)) { for (Host::TidMap::iterator it = tids_to_attach.begin(); it != tids_to_attach.end();) { @@ -423,48 +338,36 @@ Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PTRACE_ATTACH, tid); - if (error.Fail()) { + if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) { // No such thread. The thread may have exited. // More error handling may be needed. - if (error.GetError() == ESRCH) { + if (status.GetError() == ESRCH) { it = tids_to_attach.erase(it); continue; - } else - return -1; + } + return status.ToError(); } - int status; + int wpid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL); // Need to use __WALL otherwise we receive an error with errno=ECHLD // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(tid, NULL, __WALL)) < 0) { + if (wpid < 0) { // No such thread. The thread may have exited. // More error handling may be needed. if (errno == ESRCH) { it = tids_to_attach.erase(it); continue; - } else { - error.SetErrorToErrno(); - return -1; } + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); } - error = SetDefaultPtraceOpts(tid); - if (error.Fail()) - return -1; + if ((status = SetDefaultPtraceOpts(tid)).Fail()) + return status.ToError(); LLDB_LOG(log, "adding tid = {0}", tid); it->second = true; - - // Create the thread, mark it as stopped. - NativeThreadLinuxSP thread_sp(AddThread(static_cast<lldb::tid_t>(tid))); - assert(thread_sp && "AddThread() returned a nullptr"); - - // This will notify this is a new thread and tell the system it is - // stopped. - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - SetCurrentThreadID(thread_sp->GetID()); } // move the loop forward @@ -472,17 +375,16 @@ Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, } } - if (tids_to_attach.size() > 0) { - m_pid = pid; - // Let our process instance know the thread has stopped. - SetState(StateType::eStateStopped); - } else { - error.SetErrorToGenericError(); - error.SetErrorString("No such process."); - return -1; - } + size_t tid_count = tids_to_attach.size(); + if (tid_count == 0) + return llvm::make_error<StringError>("No such process", + llvm::inconvertibleErrorCode()); - return pid; + std::vector<::pid_t> tids; + tids.reserve(tid_count); + for (const auto &p : tids_to_attach) + tids.push_back(p.first); + return std::move(tids); } Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) { @@ -662,14 +564,11 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) { // The thread is not tracked yet, let's wait for it to appear. int status = -1; - ::pid_t wait_pid; - do { - LLDB_LOG(log, - "received thread creation event for tid {0}. tid not tracked " - "yet, waiting for thread to appear...", - tid); - wait_pid = waitpid(tid, &status, __WALL); - } while (wait_pid == -1 && errno == EINTR); + LLDB_LOG(log, + "received thread creation event for tid {0}. tid not tracked " + "yet, waiting for thread to appear...", + tid); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL); // Since we are waiting on a specific tid, this must be the creation event. // But let's do some checks just in case. if (wait_pid != tid) { @@ -897,11 +796,9 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, break; default: - LLDB_LOG( - log, - "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", - info.si_code, GetID(), thread.GetID()); - llvm_unreachable("Unexpected SIGTRAP code!"); + LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}", + info.si_code, GetID(), thread.GetID()); + MonitorSignal(info, thread, false); break; } } @@ -2363,15 +2260,13 @@ void NativeProcessLinux::SigchldHandler() { // Process all pending waitpid notifications. while (true) { int status = -1; - ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, + __WALL | __WNOTHREAD | WNOHANG); if (wait_pid == 0) break; // We are done. if (wait_pid == -1) { - if (errno == EINTR) - continue; - Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error); break; diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index 6bf093f6a39a..9584713d3654 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -39,15 +39,18 @@ namespace process_linux { /// /// Changes in the inferior process state are broadcasted. class NativeProcessLinux : public NativeProcessProtocol { - friend Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected<NativeProcessProtocolSP> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + llvm::Expected<NativeProcessProtocolSP> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; -public: // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- @@ -144,10 +147,10 @@ private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; - LazyBool m_supports_mem_region; + LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; - lldb::tid_t m_pending_notification_tid; + lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID; // List of thread ids stepping with a breakpoint with the address of // the relevan breakpoint @@ -156,19 +159,15 @@ private: // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- - NativeProcessLinux(); - - Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); - - /// Attaches to an existing process. Forms the - /// implementation of Process::DoAttach - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); + NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); - ::pid_t Attach(lldb::pid_t pid, Status &error); + // Returns a list of process threads that we have attached to. + static llvm::Expected<std::vector<::pid_t>> Attach(::pid_t pid); static Status SetDefaultPtraceOpts(const lldb::pid_t); - static void *MonitorThread(void *baton); + void InitializeThreads(llvm::ArrayRef<::pid_t> tids); void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status); @@ -280,7 +279,7 @@ private: // same process user id. llvm::DenseSet<lldb::tid_t> m_pt_traced_thread_group; - lldb::user_id_t m_pt_proces_trace_id; + lldb::user_id_t m_pt_proces_trace_id = LLDB_INVALID_UID; TraceOptions m_pt_process_trace_config; }; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index c3b58f16256a..1a5b304ac697 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -680,7 +680,7 @@ Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { return error; lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0, tempRefCount = 0; + uint32_t tempControl = 0; for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if (m_hwp_regs[i].control & 0x01) { @@ -858,7 +858,7 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( RegisterValue &value) { Status error; if (offset > sizeof(struct user_pt_regs)) { - uintptr_t offset = offset - sizeof(struct user_pt_regs); + offset -= sizeof(struct user_pt_regs); if (offset > sizeof(struct user_fpsimd_state)) { error.SetErrorString("invalid offset value"); return error; @@ -905,7 +905,7 @@ Status NativeRegisterContextLinux_arm64::DoWriteRegisterValue( Status error; ::pid_t tid = m_thread.GetID(); if (offset > sizeof(struct user_pt_regs)) { - uintptr_t offset = offset - sizeof(struct user_pt_regs); + offset -= sizeof(struct user_pt_regs); if (offset > sizeof(struct user_fpsimd_state)) { error.SetErrorString("invalid offset value"); return error; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 59dc9e9f7d45..e44e03b46b5c 100755 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -646,13 +646,6 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( Status error; data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) { - error.SetErrorStringWithFormat( - "failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - return error; - } - error = ReadGPR(); if (error.Fail()) return error; @@ -662,13 +655,6 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( return error; uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) @@ -741,10 +727,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( } if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + error.SetErrorStringWithFormatv( + "data_sp contained mismatched data size, expected {0}, actual {1}", + REG_CONTEXT_SIZE, data_sp->GetByteSize()); return error; } diff --git a/source/Plugins/Process/Linux/ProcessorTrace.cpp b/source/Plugins/Process/Linux/ProcessorTrace.cpp index 7043d50256e6..505c526ab70d 100644 --- a/source/Plugins/Process/Linux/ProcessorTrace.cpp +++ b/source/Plugins/Process/Linux/ProcessorTrace.cpp @@ -46,13 +46,11 @@ Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const { Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config) { - Status error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - LLDB_LOG(log, "{0}", config.getThreadID()); - #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Status error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); LLDB_LOG(log, "called thread id {0}", tid); uint64_t page_size = getpagesize(); @@ -61,12 +59,11 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, uint64_t numpages = static_cast<uint64_t>( llvm::PowerOf2Floor((bufsize + page_size - 1) / page_size)); - numpages = std::max(1ul, numpages); + numpages = std::max<uint64_t>(1, numpages); bufsize = page_size * numpages; numpages = static_cast<uint64_t>( llvm::PowerOf2Floor((metabufsize + page_size - 1) / page_size)); - numpages = std::max(0ul, numpages); metabufsize = page_size * numpages; perf_event_attr attr; @@ -117,7 +114,7 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, return error; } - m_fd = std::move(std::unique_ptr<int, file_close>(new int(fd), file_close())); + m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close()); errno = 0; auto base = @@ -129,9 +126,9 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, return error; } - m_mmap_meta = std::move(std::unique_ptr<perf_event_mmap_page, munmap_delete>( + m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>( reinterpret_cast<perf_event_mmap_page *>(base), - munmap_delete(metabufsize + page_size))); + munmap_delete(metabufsize + page_size)); m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size; m_mmap_meta->aux_size = bufsize; @@ -145,10 +142,10 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, error.SetErrorString("Trace buffer allocation failed"); return error; } - m_mmap_aux = std::move(std::unique_ptr<uint8_t, munmap_delete>( - reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize))); -#endif + m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>( + reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize)); return error; +#endif } llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetDataBuffer() { @@ -251,14 +248,14 @@ ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid, Status error; if (tid == LLDB_INVALID_THREAD_ID) { error.SetErrorString("thread not specified"); - return std::move(error.ToError()); + return error.ToError(); } ProcessorTraceMonitorUP pt_monitor_up(new ProcessorTraceMonitor); error = pt_monitor_up->StartTrace(pid, tid, config); if (error.Fail()) - return std::move(error.ToError()); + return error.ToError(); pt_monitor_up->SetThreadID(tid); @@ -274,13 +271,11 @@ ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid, Status ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - Status error; - #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Status error; uint64_t head = m_mmap_meta->aux_head; LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head); @@ -306,12 +301,12 @@ ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer, Status ProcessorTraceMonitor::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - uint64_t bytes_remaining = buffer.size(); - Status error; #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + uint64_t bytes_remaining = buffer.size(); + Status error; uint64_t head = m_mmap_meta->data_head; diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index a4d775860a65..b9ef02efa65d 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -21,6 +21,7 @@ #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/posix/ProcessLauncherPosixFork.h" #include "lldb/Target/Process.h" +#include "llvm/Support/Errno.h" // System includes - They have to be included after framework includes because // they define some @@ -63,81 +64,101 @@ static Status EnsureFDFlags(int fd, int flags) { // Public Static Methods // ----------------------------------------------------------------------------- -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { +llvm::Expected<NativeProcessProtocolSP> +NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - Status error; + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); + } - // Verify the working directory is valid if one was specified. - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && (!working_dir.ResolvePath() || - !llvm::sys::fs::is_directory(working_dir.GetPath()))) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error<StringError>("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); } + LLDB_LOG(log, "inferior started, now in stopped state"); - // Create the NativeProcessNetBSD in launch mode. - native_process_sp.reset(new NativeProcessNetBSD()); + ArchSpec arch; + if ((status = ResolveProcessArchitecture(pid, arch)).Fail()) + return status.ToError(); - if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { - native_process_sp.reset(); - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + arch.GetArchitectureName()); - error = std::static_pointer_cast<NativeProcessNetBSD>(native_process_sp) - ->LaunchInferior(mainloop, launch_info); + std::shared_ptr<NativeProcessNetBSD> process_sp(new NativeProcessNetBSD( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + arch, mainloop)); - if (error.Fail()) { - native_process_sp.reset(); - LLDB_LOG(log, "failed to launch process: {0}", error); - return error; - } + status = process_sp->ReinitializeThreads(); + if (status.Fail()) + return status.ToError(); - launch_info.SetProcessID(native_process_sp->GetID()); + for (const auto &thread_sp : process_sp->m_threads) { + static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + SIGSTOP); + } + process_sp->SetState(StateType::eStateStopped); - return error; + return process_sp; } -Status NativeProcessProtocol::Attach( +llvm::Expected<NativeProcessProtocolSP> NativeProcessNetBSD::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - return error; + ArchSpec arch; + Status status = ResolveProcessArchitecture(pid, arch); + if (!status.Success()) + return status.ToError(); - std::shared_ptr<NativeProcessNetBSD> native_process_netbsd_sp( - new NativeProcessNetBSD()); + std::shared_ptr<NativeProcessNetBSD> process_sp( + new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop)); - if (!native_process_netbsd_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } - - native_process_netbsd_sp->AttachToInferior(mainloop, pid, error); - if (!error.Success()) - return error; + status = process_sp->Attach(); + if (!status.Success()) + return status.ToError(); - native_process_sp = native_process_netbsd_sp; - return error; + return process_sp; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessNetBSD::NativeProcessNetBSD() - : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), - m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache() {} +NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, + MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + + Status status; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); +} // Handles all waitpid events from the inferior process. void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) { @@ -709,126 +730,17 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, return Status(); } -Status NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop, - ProcessLaunchInfo &launch_info) { - Status error; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; - - SetState(eStateLaunching); - - ::pid_t pid = ProcessLauncherPosixFork() - .LaunchProcess(launch_info, error) - .GetProcessId(); - if (error.Fail()) - return error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) { - error.SetErrorToErrno(); - LLDB_LOG(log, "waitpid for inferior failed with %s", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && - "Could not sync with inferior process."); - - LLDB_LOG(log, "inferior started, now in stopped state"); - - // Release the master terminal descriptor and pass it off to the - // NativeProcessNetBSD instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); - - if (m_terminal_fd != -1) { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) { - LLDB_LOG(log, - "inferior EnsureFDFlags failed for ensuring terminal " - "O_NONBLOCK setting: {0}", - error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - } - - LLDB_LOG(log, "adding pid = {0}", pid); - - ResolveProcessArchitecture(m_pid, m_arch); - - error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return error; - } - - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } - - /* Set process stopped */ - SetState(StateType::eStateStopped); - - if (error.Fail()) - LLDB_LOG(log, "inferior launching failed {0}", error); - return error; -} - -void NativeProcessNetBSD::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); - - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - m_arch.GetArchitectureName()); - - m_pid = pid; - SetState(eStateAttaching); - - Attach(pid, error); -} - void NativeProcessNetBSD::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Process all pending waitpid notifications. int status; - ::pid_t wait_pid = waitpid(GetID(), &status, WALLSIG | WNOHANG); + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG); if (wait_pid == 0) return; // We are done. if (wait_pid == -1) { - if (errno == EINTR) - return; - Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); } @@ -880,33 +792,23 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { return thread_sp; } -::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) { - if (pid <= 1) { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } - +Status NativeProcessNetBSD::Attach() { // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PT_ATTACH, pid); - if (error.Fail()) - return -1; + Status status = PtraceWrapper(PT_ATTACH, m_pid); + if (status.Fail()) + return status; - int status; + int wstatus; // Need to use WALLSIG otherwise we receive an error with errno=ECHLD // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(pid, NULL, WALLSIG)) < 0) - return -1; - - m_pid = pid; + if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0) + return Status(errno, eErrorTypePOSIX); /* Initialize threads */ - error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return -1; - } + status = ReinitializeThreads(); + if (status.Fail()) + return status; for (const auto &thread_sp : m_threads) { static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( @@ -915,8 +817,7 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); - - return pid; + return Status(); } Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf, diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 7a1303faea68..34b892f1fc88 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -31,15 +31,18 @@ namespace process_netbsd { /// /// Changes in the inferior process state are broadcasted. class NativeProcessNetBSD : public NativeProcessProtocol { - friend Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected<NativeProcessProtocolSP> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + llvm::Expected<NativeProcessProtocolSP> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; -public: // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- @@ -107,21 +110,19 @@ protected: private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; - LazyBool m_supports_mem_region; + LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- - NativeProcessNetBSD(); + NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); bool HasThreadNoLock(lldb::tid_t thread_id); NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); - Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); - void MonitorCallback(lldb::pid_t pid, int signal); void MonitorExited(lldb::pid_t pid, WaitStatus status); void MonitorSIGSTOP(lldb::pid_t pid); @@ -133,8 +134,7 @@ private: Status PopulateMemoryRegionCache(); void SigchldHandler(); - ::pid_t Attach(lldb::pid_t pid, Status &error); - + Status Attach(); Status ReinitializeThreads(); }; diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt index 3d008f42499d..5e51feef1d3f 100644 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -7,14 +7,6 @@ set(LLDB_PLUGINS lldbPluginPlatformMacOSX ) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") - list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") - list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) -endif() - add_lldb_library(lldbPluginProcessGDBRemote PLUGIN GDBRemoteClientBase.cpp GDBRemoteCommunication.cpp diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 33aed7a43c4a..e6fd386b903b 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -86,6 +86,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), m_supports_QPassSignals(eLazyBoolCalculate), + m_supports_error_string_reply(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -596,6 +597,21 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { return m_supports_jThreadExtendedInfo; } +void GDBRemoteCommunicationClient::EnableErrorStringInPacket() { + if (m_supports_error_string_reply == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + // We try to enable error strings in remote packets + // but if we fail, we just work in the older way. + m_supports_error_string_reply = eLazyBoolNo; + if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_error_string_reply = eLazyBoolYes; + } + } + } +} + bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { StringExtractorGDBRemote response; @@ -3181,8 +3197,8 @@ GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsNormalResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); - LLDB_LOG(log, "Target does not support Tracing"); + error = response.GetStatus(); + LLDB_LOG(log, "Target does not support Tracing , error {0}", error); } else { ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); } @@ -3219,7 +3235,7 @@ GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsOKResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); LLDB_LOG(log, "stop tracing failed"); } } else { @@ -3234,6 +3250,7 @@ GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, Status GDBRemoteCommunicationClient::SendGetDataPacket( lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceBufferRead:"); return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); @@ -3242,6 +3259,7 @@ Status GDBRemoteCommunicationClient::SendGetDataPacket( Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceMetaRead:"); return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); @@ -3308,7 +3326,7 @@ GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, custom_params_sp)); } } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); } } else { LLDB_LOG(log, "failed to send packet"); @@ -3344,7 +3362,7 @@ Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( size_t filled_size = response.GetHexBytesAvail(buffer); buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size); } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); buffer = buffer.slice(buffer.size()); } } else { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index a38110faaec6..712d85eed082 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -340,6 +340,8 @@ public: bool GetQXferAuxvReadSupported(); + void EnableErrorStringInPacket(); + bool GetQXferLibrariesReadSupported(); bool GetQXferLibrariesSVR4ReadSupported(); @@ -549,6 +551,7 @@ protected: LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; LazyBool m_supports_QPassSignals; + LazyBool m_supports_error_string_reply; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index dac675ee9432..4be92b79fd1a 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -20,6 +20,7 @@ // Project includes #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; @@ -27,7 +28,12 @@ using namespace lldb_private::process_gdb_remote; GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( const char *comm_name, const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {} + : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) { + RegisterPacketHandler( + StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings, + [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, + bool &quit) { return this->Handle_QErrorStringEnable(packet); }); +} GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} @@ -100,6 +106,24 @@ GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) { } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) { + if (m_send_error_strings) { + lldb_private::StreamString packet; + packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError())); + packet.PutCStringAsRawHex8(error.AsCString()); + return SendPacketNoLock(packet.GetString()); + } else + return SendErrorResponse(error.GetError()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_QErrorStringEnable( + StringExtractorGDBRemote &packet) { + m_send_error_strings = true; + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 6eb25f8b9f98..a35352480040 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -57,6 +57,13 @@ protected: bool m_exit_now; // use in asynchronous handling to indicate process should // exit. + bool m_send_error_strings; // If the client enables this then + // we will send error strings as well. + + PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet); + + PacketResult SendErrorResponse(const Status &error); + PacketResult SendUnimplementedResponse(const char *packet); PacketResult SendErrorResponse(uint8_t error); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index de2400c51ba3..f53db502be93 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -1046,14 +1046,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { if (success) { m_process_launch_error = LaunchProcess(); - if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { + if (m_process_launch_error.Success()) return SendOKResponse(); - } else { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("LLGSPacketHandler::%s failed to launch exe: %s", - __FUNCTION__, m_process_launch_error.AsCString()); - } + LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error); } return SendErrorResponse(8); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 7523260c13e4..a7fe4ee3b147 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -73,15 +73,11 @@ enum GDBRemoteServerError { // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( - MainLoop &mainloop) + MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID), - m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(), - m_debugged_process_sp(), m_stdio_communication("process.stdio"), - m_inferior_prev_state(StateType::eStateInvalid), - m_saved_registers_map(), m_next_saved_registers_id(1), - m_handshake_completed(false) { + m_mainloop(mainloop), m_process_factory(process_factory), + m_stdio_communication("process.stdio") { RegisterPacketHandlers(); } @@ -241,19 +237,20 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { const bool default_to_use_pty = true; m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); - Status error; { std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); assert(!m_debugged_process_sp && "lldb-server creating debugged " "process but one already exists"); - error = NativeProcessProtocol::Launch(m_process_launch_info, *this, - m_mainloop, m_debugged_process_sp); - } - - if (!error.Success()) { - fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, - m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); - return error; + auto process_or = + m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv( + "failed to launch executable `{0}`: {1}", + m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); + return status; + } + m_debugged_process_sp = *process_or; } // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol @@ -279,9 +276,9 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " @@ -298,14 +295,12 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { printf("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments().GetArgumentAtIndex(0), - m_process_launch_info.GetProcessID()); + m_debugged_process_sp->GetID()); - return error; + return Status(); } Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { - Status error; - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, @@ -321,13 +316,14 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { pid, m_debugged_process_sp->GetID()); // Try to attach. - error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, - m_debugged_process_sp); - if (!error.Success()) { - fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s", - __FUNCTION__, pid, error.AsCString()); - return error; + auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid, + status); + return status; } + m_debugged_process_sp = *process_or; // Setup stdout/stderr mapping from inferior. auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); @@ -336,9 +332,9 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " @@ -347,8 +343,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { } printf("Attached to process %" PRIu64 "...\n", pid); - - return error; + return Status(); } void GDBRemoteCommunicationServerLLGS::InitializeDelegate( @@ -1128,7 +1123,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( uid = m_debugged_process_sp->StartTrace(options, error); LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError()); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote response; response.Printf("%" PRIx64, uid); @@ -1165,7 +1160,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( Status error = m_debugged_process_sp->StopTrace(uid, tid); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); return SendOKResponse(); } @@ -1208,7 +1203,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( Status error = m_debugged_process_sp->GetTraceConfig(uid, options); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote escaped_response; StructuredData::Dictionary json_packet; @@ -1284,7 +1279,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); for (auto i : buf) response.PutHex8(i); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index a7d7850d454f..b065642d4aed 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -39,7 +39,9 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); + GDBRemoteCommunicationServerLLGS( + MainLoop &mainloop, + const NativeProcessProtocol::Factory &process_factory); //------------------------------------------------------------------ /// Specify the program to launch and its arguments. @@ -108,20 +110,21 @@ public: protected: MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; - lldb::tid_t m_current_tid; - lldb::tid_t m_continue_tid; + const NativeProcessProtocol::Factory &m_process_factory; + lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID; std::recursive_mutex m_debugged_process_mutex; NativeProcessProtocolSP m_debugged_process_sp; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; - lldb::StateType m_inferior_prev_state; + lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid; std::unique_ptr<llvm::MemoryBuffer> m_active_auxv_buffer_up; std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; - uint32_t m_next_saved_registers_id; - bool m_handshake_completed : 1; + uint32_t m_next_saved_registers_id = 1; + bool m_handshake_completed = false; PacketResult SendONotification(const char *buffer, uint32_t len); diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 042c96111bb3..8a66f3865ebc 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1031,6 +1031,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { m_gdb_comm.GetHostInfo(); m_gdb_comm.GetVContSupported('c'); m_gdb_comm.GetVAttachOrWaitSupported(); + m_gdb_comm.EnableErrorStringInPacket(); // Ask the remote server for the default thread id if (GetTarget().GetNonStopModeEnabled()) diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index b7fbd7347d08..6c39690268c6 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1857,14 +1857,12 @@ StructuredData::DictionarySP ScriptInterpreterPython::GetDynamicSettings( return StructuredData::DictionarySP(); PythonObject reply_pyobj; - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - TargetSP target_sp(target->shared_from_this()); - reply_pyobj.Reset(PyRefType::Owned, - (PyObject *)g_swig_plugin_get(generic->GetValue(), - setting_name, target_sp)); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + TargetSP target_sp(target->shared_from_this()); + reply_pyobj.Reset(PyRefType::Owned, + (PyObject *)g_swig_plugin_get(generic->GetValue(), + setting_name, target_sp)); PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); return py_dict.CreateStructuredDictionary(); diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 9d79a411faad..aa15063ac0dc 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -604,9 +604,10 @@ uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) { } bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p, - int &length) { + int &length, + uint32_t buffer_remaining_bytes) { - const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize(); + uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize()); llvm::SmallVector<uint8_t, 32> opcode_data; opcode_data.resize(max_op_byte_size); @@ -698,8 +699,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( bool row_updated = false; // The UnwindPlan::Row 'row' has been updated m_cur_insn = data + current_func_text_offset; - if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || - insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset) + || insn_len == 0 + || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction break; } @@ -1002,8 +1004,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( while (offset < size) { m_cur_insn = data + offset; int insn_len; - if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || - insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) + || insn_len == 0 + || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction. break; } @@ -1214,8 +1217,9 @@ bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction( int scratch; m_cur_insn = data + offset; - if (!instruction_length(m_cur_insn, insn_len) || - insn_len > kMaxInstructionByteSize || insn_len == 0) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) + || insn_len > kMaxInstructionByteSize + || insn_len == 0) { // An error parsing the instruction, i.e. probably data/garbage - stop // scanning break; diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h index 2e7875966cb6..97441d362973 100644 --- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h +++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h @@ -113,7 +113,7 @@ private: bool ret_pattern_p(); uint32_t extract_4(uint8_t *b); - bool instruction_length(uint8_t *insn, int &length); + bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes); bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno); diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp index 3473a9e96689..8e50c0106a48 100644 --- a/source/Utility/StringExtractorGDBRemote.cpp +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -19,8 +19,18 @@ StringExtractorGDBRemote::GetResponseType() const { switch (m_packet[0]) { case 'E': - if (m_packet.size() == 3 && isxdigit(m_packet[1]) && isxdigit(m_packet[2])) - return eError; + if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) { + if (m_packet.size() == 3) + return eError; + llvm::StringRef packet_ref(m_packet); + if (packet_ref[3] == ';') { + auto err_string = packet_ref.substr(4); + for (auto e : err_string) + if (!isxdigit(e)) + return eResponse; + return eError; + } + } break; case 'O': @@ -86,6 +96,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_QEnvironment; if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded; + if (PACKET_STARTS_WITH("QEnableErrorStrings")) + return eServerPacketType_QEnableErrorStrings; break; case 'P': @@ -438,8 +450,8 @@ bool StringExtractorGDBRemote::IsNormalResponse() const { } bool StringExtractorGDBRemote::IsErrorResponse() const { - return GetResponseType() == eError && m_packet.size() == 3 && - isxdigit(m_packet[1]) && isxdigit(m_packet[2]); + return GetResponseType() == eError && isxdigit(m_packet[1]) && + isxdigit(m_packet[2]); } uint8_t StringExtractorGDBRemote::GetError() { @@ -450,6 +462,23 @@ uint8_t StringExtractorGDBRemote::GetError() { return 0; } +lldb_private::Status StringExtractorGDBRemote::GetStatus() { + lldb_private::Status error; + if (GetResponseType() == eError) { + SetFilePos(1); + uint8_t errc = GetHexU8(255); + error.SetError(errc, lldb::eErrorTypeGeneric); + + error.SetErrorStringWithFormat("Error %u", errc); + std::string error_messg; + if (GetChar() == ';') { + GetHexByteString(error_messg); + error.SetErrorString(error_messg); + } + } + return error; +} + size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) { // Just get the data bytes in the string as // GDBRemoteCommunication::CheckForPacket() diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h index 473cab04f800..f4ed642a706e 100644 --- a/source/Utility/StringExtractorGDBRemote.h +++ b/source/Utility/StringExtractorGDBRemote.h @@ -10,6 +10,7 @@ #ifndef utility_StringExtractorGDBRemote_h_ #define utility_StringExtractorGDBRemote_h_ +#include "lldb/Utility/Status.h" #include "lldb/Utility/StringExtractor.h" #include "llvm/ADT/StringRef.h" // for StringRef @@ -72,6 +73,7 @@ public: eServerPacketType_qGetWorkingDir, eServerPacketType_qFileLoadAddress, eServerPacketType_QEnvironment, + eServerPacketType_QEnableErrorStrings, eServerPacketType_QLaunchArch, eServerPacketType_QSetDisableASLR, eServerPacketType_QSetDetachOnError, @@ -190,6 +192,8 @@ public: // digits. Otherwise the error encoded in XX is returned. uint8_t GetError(); + lldb_private::Status GetStatus(); + size_t GetEscapedBinaryData(std::string &str); protected: diff --git a/tools/lldb-server/CMakeLists.txt b/tools/lldb-server/CMakeLists.txt index 4f76ebd6881c..f8c57cb9488f 100644 --- a/tools/lldb-server/CMakeLists.txt +++ b/tools/lldb-server/CMakeLists.txt @@ -59,6 +59,16 @@ if (LLVM_BUILD_STATIC) endif() endif() +set(LLDB_PLUGINS) + +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) +endif() + add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK Acceptor.cpp lldb-gdbserver.cpp @@ -72,7 +82,7 @@ add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK lldbHost lldbInitialization lldbInterpreter - ${EXTRA_LLDB_LIBS} + ${LLDB_PLUGINS} ${LLDB_SYSTEM_LIBS} LINK_COMPONENTS diff --git a/tools/lldb-server/lldb-gdbserver.cpp b/tools/lldb-server/lldb-gdbserver.cpp index 412d775e8394..337f244c2c2d 100644 --- a/tools/lldb-server/lldb-gdbserver.cpp +++ b/tools/lldb-server/lldb-gdbserver.cpp @@ -33,10 +33,17 @@ #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Utility/Status.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Errno.h" +#if defined(__linux__) +#include "Plugins/Process/Linux/NativeProcessLinux.h" +#elif defined(__NetBSD__) +#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" +#endif + #ifndef LLGS_PROGRAM_NAME #define LLGS_PROGRAM_NAME "lldb-server" #endif @@ -51,6 +58,30 @@ using namespace lldb_private; using namespace lldb_private::lldb_server; using namespace lldb_private::process_gdb_remote; +namespace { +#if defined(__linux__) +typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory; +#elif defined(__NetBSD__) +typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory; +#else +// Dummy implementation to make sure the code compiles +class NativeProcessFactory : public NativeProcessProtocol::Factory { +public: + llvm::Expected<NativeProcessProtocolSP> + Launch(ProcessLaunchInfo &launch_info, + NativeProcessProtocol::NativeDelegate &delegate, + MainLoop &mainloop) const override { + llvm_unreachable("Not implemented"); + } + llvm::Expected<NativeProcessProtocolSP> + Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate, + MainLoop &mainloop) const override { + llvm_unreachable("Not implemented"); + } +}; +#endif +} + //---------------------------------------------------------------------- // option descriptors for getopt_long_only() //---------------------------------------------------------------------- @@ -446,7 +477,8 @@ int main_gdbserver(int argc, char *argv[]) { exit(255); } - GDBRemoteCommunicationServerLLGS gdb_server(mainloop); + NativeProcessFactory factory; + GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory); const char *const host_and_port = argv[0]; argc -= 1; diff --git a/tools/lldb-server/lldb-platform.cpp b/tools/lldb-server/lldb-platform.cpp index 8d45682566b9..ec5b781dac48 100644 --- a/tools/lldb-server/lldb-platform.cpp +++ b/tools/lldb-server/lldb-platform.cpp @@ -197,46 +197,41 @@ int main_platform(int argc, char *argv[]) { break; case 'p': { - char *end = NULL; - long tmp_port_offset = strtoul(optarg, &end, 0); - if (end && *end == '\0') { - if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT) { - port_offset = (uint16_t)tmp_port_offset; - } else { - fprintf(stderr, "error: port offset %li is not in the valid user " - "port range of %u - %u\n", - tmp_port_offset, LOW_PORT, HIGH_PORT); - option_error = 5; - } - } else { - fprintf(stderr, "error: invalid port offset string %s\n", optarg); + if (!llvm::to_integer(optarg, port_offset)) { + llvm::errs() << "error: invalid port offset string " << optarg << "\n"; option_error = 4; + break; + } + if (port_offset < LOW_PORT || port_offset > HIGH_PORT) { + llvm::errs() << llvm::formatv("error: port offset {0} is not in the " + "valid user port range of {1} - {2}\n", + port_offset, LOW_PORT, HIGH_PORT); + option_error = 5; } } break; case 'P': case 'm': case 'M': { - char *end = NULL; - long portnum = strtoul(optarg, &end, 0); - if (end && *end == '\0') { - if (LOW_PORT <= portnum && portnum <= HIGH_PORT) { - if (ch == 'P') - gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID; - else if (ch == 'm') - min_gdbserver_port = portnum; - else - max_gdbserver_port = portnum; - } else { - fprintf(stderr, "error: port number %li is not in the valid user " - "port range of %u - %u\n", - portnum, LOW_PORT, HIGH_PORT); - option_error = 1; - } - } else { - fprintf(stderr, "error: invalid port number string %s\n", optarg); + uint16_t portnum; + if (!llvm::to_integer(optarg, portnum)) { + llvm::errs() << "error: invalid port number string " << optarg << "\n"; option_error = 2; + break; + } + if (portnum < LOW_PORT || portnum > HIGH_PORT) { + llvm::errs() << llvm::formatv("error: port number {0} is not in the " + "valid user port range of {1} - {2}\n", + portnum, LOW_PORT, HIGH_PORT); + option_error = 1; + break; } + if (ch == 'P') + gdbserver_portmap[portnum] = LLDB_INVALID_PROCESS_ID; + else if (ch == 'm') + min_gdbserver_port = portnum; + else + max_gdbserver_port = portnum; } break; case 'h': /* fall-through is intentional */ diff --git a/unittests/Process/Linux/ProcessorTraceTest.cpp b/unittests/Process/Linux/ProcessorTraceTest.cpp index b732934d014d..67381b6ddca3 100644 --- a/unittests/Process/Linux/ProcessorTraceTest.cpp +++ b/unittests/Process/Linux/ProcessorTraceTest.cpp @@ -30,42 +30,40 @@ size_t ReadCylicBufferWrapper(void *buf, size_t buf_size, void *cyc_buf, } TEST(CyclicBuffer, EdgeCases) { - size_t bytes_read = 0; + size_t bytes_read; uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; // We will always leave the last bytes untouched // so that string comparisions work. - char bigger_buffer[10] = {}; - char equal_size_buffer[7] = {}; char smaller_buffer[4] = {}; // empty buffer to read into bytes_read = ReadCylicBufferWrapper(smaller_buffer, 0, cyclic_buffer, sizeof(cyclic_buffer), 3, 0); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // empty cyclic buffer bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, 0, 3, 0); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // bigger offset bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, 6); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // wrong offset bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, 7); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // wrong start bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, 7); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); } TEST(CyclicBuffer, EqualSizeBuffer) { @@ -73,7 +71,7 @@ TEST(CyclicBuffer, EqualSizeBuffer) { uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; char cyclic[] = "cyclic"; - for (int i = 0; i < sizeof(cyclic); i++) { + for (size_t i = 0; i < sizeof(cyclic); i++) { // We will always leave the last bytes untouched // so that string comparisions work. char equal_size_buffer[7] = {}; @@ -86,7 +84,7 @@ TEST(CyclicBuffer, EqualSizeBuffer) { } TEST(CyclicBuffer, SmallerSizeBuffer) { - size_t bytes_read = 0; + size_t bytes_read; uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; // We will always leave the last bytes untouched @@ -95,25 +93,25 @@ TEST(CyclicBuffer, SmallerSizeBuffer) { bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 0); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "cyc"); bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 1); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "ycl"); bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 2); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "cli"); bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 3); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "lic"); { @@ -121,7 +119,7 @@ TEST(CyclicBuffer, SmallerSizeBuffer) { bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 4); - ASSERT_EQ(2, bytes_read); + ASSERT_EQ(2u, bytes_read); ASSERT_STREQ(smaller_buffer, "ic"); } { @@ -129,7 +127,7 @@ TEST(CyclicBuffer, SmallerSizeBuffer) { bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 5); - ASSERT_EQ(1, bytes_read); + ASSERT_EQ(1u, bytes_read); ASSERT_STREQ(smaller_buffer, "c"); } } @@ -139,7 +137,7 @@ TEST(CyclicBuffer, BiggerSizeBuffer) { uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; char cyclic[] = "cyclic"; - for (int i = 0; i < sizeof(cyclic); i++) { + for (size_t i = 0; i < sizeof(cyclic); i++) { // We will always leave the last bytes untouched // so that string comparisions work. char bigger_buffer[10] = {}; diff --git a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp index e97760967197..c3591b2d73e1 100644 --- a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp +++ b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp @@ -2415,3 +2415,28 @@ TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) { EXPECT_EQ(rsp_plus_8, plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue()); } + +// Give the disassembler random bytes to test that it doesn't exceed +// the bounds of the array when run under clang's address sanitizer. +TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) { + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector(); + std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector(); + + uint8_t data[] = { + 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + sample_range = AddressRange(0x1000, sizeof(data)); + + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + unwind_plan.Clear(); + + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + +} + diff --git a/www/architecture.html b/www/architecture.html deleted file mode 100755 index eb178febde54..000000000000 --- a/www/architecture.html +++ /dev/null @@ -1,294 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> -<link href="style.css" rel="stylesheet" type="text/css" /> -<title>LLDB Architecture</title> -</head> - -<body> - <div class="www_title"> - The <strong>LLDB</strong> Debugger - </div> - -<div id="container"> - <div id="content"> - - <!--#include virtual="sidebar.incl"--> - - <div id="middle"> - <div class="post"> - <h1 class ="postheader">Architecture</h1> - <div class="postcontent"> - - <p>LLDB is a large and complex codebase. This section will help you become more familiar with - the pieces that make up LLDB and give a general overview of the general architecture.</p> - </div> - <div class="postfooter"></div> - </div> - <div class="post"> - <h1 class ="postheader">Code Layout</h1> - <div class="postcontent"> - - <p>LLDB has many code groupings that makeup the source base:</p> - <ul> - <li><a href="#api">API</a></li> - <li><a href="#breakpoint">Breakpoint</a></li> - <li><a href="#commands">Commands</a></li> - <li><a href="#core">Core</a></li> - <li><a href="#dataformatters">DataFormatters</a></li> - <li><a href="#expression">Expression</a></li> - <li><a href="#host">Host</a></li> - <li><a href="#interpreter">Interpreter</a></li> - <li><a href="#symbol">Symbol</a></li> - <li><a href="#targ">Target</a></li> - <li><a href="#utility">Utility</a></li> - </ul> - </div> - <div class="postfooter"></div> - </div> - <a name="api"></a> - <div class="post"> - <h1 class ="postheader">API</h1> - <div class="postcontent"> - - <p>The API folder contains the public interface to LLDB.</p> - <p>We are currently vending a C++ API. In order to be able to add - methods to this API and allow people to link to our classes, - we have certain rules that we must follow:</p> - <ul> - <li>Classes can't inherit from any other classes.</li> - <li>Classes can't contain virtual methods.</li> - <li>Classes should be compatible with script bridging utilities like <a href="http://www.swig.org/">swig</a>.</li> - <li>Classes should be lightweight and be backed by a single member. Pointers (or shared pointers) are the preferred choice since they allow changing the contents of the backend without affecting the public object layout.</li> - <li>The interface should be as minimal as possible in order to give a complete API.</li> - </ul> - <p>By adhering to these rules we should be able to continue to - vend a C++ API, and make changes to the API as any additional - methods added to these classes will just be a dynamic loader - lookup and they won't affect the class layout (since they - aren't virtual methods, and no members can be added to the - class).</p> - </div> - <div class="postfooter"></div> - </div> - <a name="breakpoint"></a> - <div class="post"> - <h1 class ="postheader">Breakpoint</h1> - <div class="postcontent"> - - <p>A collection of classes that implement our breakpoint classes. - Breakpoints are resolved symbolically and always continue to - resolve themselves as your program runs. Whether settings breakpoints - by file and line, by symbol name, by symbol regular expression, - or by address, breakpoints will keep trying to resolve new locations - each time shared libraries are loaded. Breakpoints will of course - unresolve themselves when shared libraries are unloaded. Breakpoints - can also be scoped to be set only in a specific shared library. By - default, breakpoints can be set in any shared library and will continue - to attempt to be resolved with each shared library load.</p> - <p>Breakpoint options can be set on the breakpoint, - or on the individual locations. This allows flexibility when dealing - with breakpoints and allows us to do what the user wants.</p> - </div> - <div class="postfooter"></div> - </div> - <a name="commands"></a> - <div class="post"> - <h1 class ="postheader">Commands</h1> - <div class="postcontent"> - - <p>The command source files represent objects that implement - the functionality for all textual commands available - in our command line interface.</p> - <p>Every command is backed by a <b>lldb_private::CommandObject</b> - or <b>lldb_private::CommandObjectMultiword</b> object.</p> - <p><b>lldb_private::CommandObjectMultiword</b> are commands that - have subcommands and allow command line commands to be - logically grouped into a hierarchy.</p> - <p><b>lldb_private::CommandObject</b> command line commands - are the objects that implement the functionality of the - command. They can optionally define - options for themselves, as well as group those options into - logical groups that can go together. The help system is - tied into these objects and can extract the syntax and - option groupings to display appropriate help for each - command.</p> - </div> - <div class="postfooter"></div> - </div> - <a name="core"></a> - <div class="post"> - <h1 class ="postheader">Core</h1> - <div class="postcontent"> - - <p>The Core source files contain basic functionality that - is required in the debugger. A wide variety of classes - are implemented:</p> - - <ul> - <li>Address (section offset addressing)</li> - <li>AddressRange</li> - <li>Architecture specification</li> - <li>Broadcaster / Event / Listener </li> - <li>Communication classes that use Connection objects</li> - <li>Uniqued C strings</li> - <li>Data extraction</li> - <li>File specifications</li> - <li>Mangled names</li> - <li>Regular expressions</li> - <li>Source manager</li> - <li>Streams</li> - <li>Value objects</li> - </ul> - </div> - <div class="postfooter"></div> - </div> - <a name="dataformatters"></a> - <div class="post"> - <h1 class ="postheader">DataFormatters</h1> - <div class="postcontent"> - - <p>A collection of classes that implement the data formatters subsystem.</p> - - <p>For a general user-level introduction to data formatters, you can look <a href="varformats.html">here</a>. - <p>A 10,000 foot view of the data formatters is based upon the <code>DataVisualization</code> class. - <code>DataVisualization</code> is the very high level entry point into the data formatters. It vends a stable interface in face of changing internals - and is the recommended entry point for components of LLDB that need to ask questions of the data formatters. - The main questions one can ask of <code>DataVisualization</code> are: - <ul> - <li>given a ValueObject, retrieve the formatters to be used for it</li> - <li>given a type, retrieve the formatters to be used for it. This is not an "exact" question, - i.e. one can retrieve a formatter from a type name which would not be used to then format ValueObjects of that type</li> - <li>given a name, retrieve a category of that name, optionally creating it if needed - more generally, categories management</li> - <li>given an identifier and a summary, store it as a named summary - more generally, named summary management</li> - </ul> - - <p>For people actively maintaining the data formatters subsystem itself, however, the FormatManager class is the relevant point of entry. - This class is subject to more frequent changes as the formatters evolve. Currently, it provides a thin caching layer on top of a list of categories - that each export a group of formatters. - </p> - <p>From an end-user perspective, the "type" LLDB command is the point of access to the data formatters. A large group of generally-useful formatters - is provided by default and loaded upon debugger startup. - </div> - <div class="postfooter"></div> - </div> - <a name="expression"></a> - <div class="post"> - <h1 class ="postheader">Expression</h1> - <div class="postcontent"> - - <p>Expression parsing files cover everything from evaluating - DWARF expressions, to evaluating expressions using - Clang.</p> - <p>The DWARF expression parser has been heavily modified to - support type promotion, new opcodes needed for evaluating - expressions with symbolic variable references (expression local variables, - program variables), and other operators required by - typical expressions such as assign, address of, float/double/long - double floating point values, casting, and more. The - DWARF expression parser uses a stack of lldb_private::Value - objects. These objects know how to do the standard C type - promotion, and allow for symbolic references to variables - in the program and in the LLDB process (expression local - and expression global variables).</p> - <p>The expression parser uses a full instance of the Clang - compiler in order to accurately evaluate expressions. - Hooks have been put into Clang so that the compiler knows - to ask about identifiers it doesn't know about. Once - expressions have be compiled into an AST, we can then - traverse this AST and either generate a DWARF expression - that contains simple opcodes that can be quickly re-evaluated - each time an expression needs to be evaluated, or JIT'ed - up into code that can be run on the process being debugged.</p> - </div> - <div class="postfooter"></div> - </div> - <a name="host"></a> - <div class="post"> - <h1 class ="postheader">Host</h1> - <div class="postcontent"> - - <p>LLDB tries to abstract itself from the host upon which - it is currently running by providing a host abstraction - layer. This layer involves everything from spawning, detaching, - joining and killing native in-process threads, to getting - current information about the current host.</p> - <p>Host functionality includes abstraction layers for:</p> - <ul> - <li>Mutexes</li> - <li>Conditions</li> - <li>Timing functions</li> - <li>Thread functions</li> - <li>Host target triple</li> - <li>Host child process notifications</li> - <li>Host specific types</li> - </ul> - </div> - <div class="postfooter"></div> - </div> - <a name="interpreter"></a> - <div class="post"> - <h1 class ="postheader">Interpreter</h1> - <div class="postcontent"> - - <p>The interpreter classes are the classes responsible for - being the base classes needed for each command object, - and is responsible for tracking and running command line - commands.</p> - </div> - <div class="postfooter"></div> - </div> - <a name="symbol"></a> - <div class="post"> - <h1 class ="postheader">Symbol</h1> - <div class="postcontent"> - <p>Symbol classes involve everything needed in order to parse - object files and debug symbols. All the needed classes - for compilation units (code and debug info for a source file), - functions, lexical blocks within functions, inlined - functions, types, declaration locations, and variables - are in this section.</p> - </div> - <div class="postfooter"></div> - </div> - <a name="targ"></a> - <div class="post"> - <h1 class ="postheader">Target</h1> - <div class="postcontent"> - - <p>Classes that are related to a debug target include:</p> - <ul> - <li>Target</li> - <li>Process</li> - <li>Thread</li> - <li>Stack frames</li> - <li>Stack frame registers</li> - <li>ABI for function calling in process being debugged</li> - <li>Execution context batons</li> - </ul> - </div> - <div class="postfooter"></div> - </div> - <a name="utility"></a> - <div class="post"> - <h1 class ="postheader">Utility</h1> - <div class="postcontent"> - - <p>Utility files should be as stand alone as possible and - available for LLDB, plug-ins or related - applications to use.</p> - <p>Files found in the Utility section include:</p> - <ul> - <li>Pseudo-terminal support</li> - <li>Register numbering for specific architectures.</li> - <li>String data extractors</li> - </ul> - </div> - <div class="postfooter"></div> - </div> - </div> - </div> -</div> -</body> -</html> diff --git a/www/architecture/index.html b/www/architecture/index.html index fd75603f6405..312476fe6edf 100755 --- a/www/architecture/index.html +++ b/www/architecture/index.html @@ -119,30 +119,26 @@ </div> <a name="core"></a> <div class="post"> - <h1 class ="postheader">Core</h1> - <div class="postcontent"> - - <p>The Core source files contain basic functionality that - is required in the debugger. A wide variety of classes - are implemented:</p> - - <ul> - <li>Address (section offset addressing)</li> - <li>AddressRange</li> - <li>Architecture specification</li> - <li>Broadcaster / Event / Listener </li> - <li>Communication classes that use Connection objects</li> - <li>Uniqued C strings</li> - <li>Data extraction</li> - <li>File specifications</li> - <li>Mangled names</li> - <li>Regular expressions</li> - <li>Source manager</li> - <li>Streams</li> - <li>Value objects</li> - </ul> - </div> - <div class="postfooter"></div> + <h1 class ="postheader">Core</h1> + <div class="postcontent"> + <p> + The Core source files contain basic functionality + that is required in the debugger as well as the + class represeting the debugger it self (Debugger). A + wide variety of classes are implemented: + </p> + <ul> + <li>Address (section offset addressing)</li> + <li>AddressRange</li> + <li>Architecture specification</li> + <li>Broadcaster / Event / Listener </li> + <li>Communication classes that use Connection objects</li> + <li>Mangled names</li> + <li>Source manager</li> + <li>Value objects</li> + </ul> + </div> + <div class="postfooter"></div> </div> <a name="dataformatters"></a> <div class="post"> @@ -193,26 +189,27 @@ </div> <a name="host"></a> <div class="post"> - <h1 class ="postheader">Host</h1> - <div class="postcontent"> - - <p>LLDB tries to abstract itself from the host upon which - it is currently running by providing a host abstraction - layer. This layer involves everything from spawning, detaching, - joining and killing native in-process threads, to getting - current information about the current host.</p> - <p>Host functionality includes abstraction layers for:</p> - <ul> - <li>Mutexes</li> - <li>Conditions</li> - <li>Timing functions</li> - <li>Thread functions</li> - <li>Host target triple</li> - <li>Host child process notifications</li> - <li>Host specific types</li> - </ul> - </div> - <div class="postfooter"></div> + <h1 class ="postheader">Host</h1> + <div class="postcontent"> + <p> + LLDB tries to abstract itself from the host upon which + it is currently running by providing a host abstraction + layer. This layer includes functionality, whose + implementation varies wildly from host to host. + </p> + <p>Host functionality includes abstraction layers for:</p> + <ul> + <li>Information about the host system (triple, list of running processes, etc.)</li> + <li>Launching processes</li> + <li>Various OS primitives like pipes and sockets</li> + </ul> + <p> + It also includes the base classes of the + NativeProcess/Thread hierarchy, which is used by + lldb-server. + </p> + </div> + <div class="postfooter"></div> </div> <a name="interpreter"></a> <div class="post"> @@ -259,20 +256,40 @@ </div> <a name="utility"></a> <div class="post"> - <h1 class ="postheader">Utility</h1> - <div class="postcontent"> - - <p>Utility files should be as stand alone as possible and - available for LLDB, plug-ins or related - applications to use.</p> - <p>Files found in the Utility section include:</p> - <ul> - <li>Pseudo-terminal support</li> - <li>Register numbering for specific architectures.</li> - <li>String data extractors</li> - </ul> - </div> - <div class="postfooter"></div> + <h1 class ="postheader">Utility</h1> + <div class="postcontent"> + <p> + This module contains the lowest layers of LLDB. A + lot of these classes don't really have anything to + do with debugging -- they are just there because the + higher layers of the debugger use these clasess + to implement their functionality. Others are data + structures used in many other parts of the debugger + (TraceOptions). Most of the functionality in this + module could be useful in an application that is + <strong>not</strong> a debugger; however, providing + a general purpose C++ library is an explicit + non-goal of this module. + </p> + <p> + This module provides following functionality: + </p> + <ul> + <li>Abstract path manipulation (FileSpec)</li> + <li>Data buffers (DataBuffer, DataEncoder, DataExtractor)</li> + <li>Logging</li> + <li>Structured data manipulation (JSON)</li> + <li>Streams</li> + <li>Timers</li> + <li>etc.</li> + </ul> + <p> + For historic reasons, some of this functionality + overlaps that which is provided by the LLVM support + library. + </p> + </div> + <div class="postfooter"></div> </div> </div> </div> diff --git a/www/sidebar.incl b/www/sidebar.incl index 184a022790e2..8c5cca373653 100644 --- a/www/sidebar.incl +++ b/www/sidebar.incl @@ -49,7 +49,7 @@ <li><a href="/build.html">Build</a></li> <li><a href="/test.html">Test</a></li> <li><a href="/SB-api-coding-rules.html">SB API Coding Rules</a></li> - <li><a href="http://llvm.org/bugs">Bug Reports</a></li> + <li><a href="http://bugs.llvm.org">Bug Reports</a></li> <li><a href="http://llvm.org/svn/llvm-project/lldb/trunk">Browse SVN</a></li> <li><a href="http://llvm.org/viewvc/llvm-project/lldb/trunk">Browse ViewVC</a></li> </ul> |