diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:31:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:31:19 +0000 |
commit | 773dd0e6e632d48d7123a321ba86f50847b9afc0 (patch) | |
tree | c6bd992bb1963df11f8de346d12a5a70c2e4deb2 | |
parent | 5060b64b7d79491d507a75201be161fd0c38fcbb (diff) |
Notes
71 files changed, 1543 insertions, 1040 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index fe640fedb038..ada293811b3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,15 @@ cmake_minimum_required(VERSION 3.4.3) -include(cmake/modules/LLDBStandalone.cmake) -include(cmake/modules/LLDBConfig.cmake) -include(cmake/modules/AddLLDB.cmake) +# Add path for custom modules +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + ) + +include(LLDBStandalone) +include(LLDBConfig) +include(AddLLDB) if (CMAKE_SYSTEM_NAME MATCHES "Windows|Android") set(LLDB_DEFAULT_DISABLE_LIBEDIT 1) diff --git a/cmake/XcodeHeaderGenerator/CMakeLists.txt b/cmake/XcodeHeaderGenerator/CMakeLists.txt new file mode 100644 index 000000000000..f515c5fb8c46 --- /dev/null +++ b/cmake/XcodeHeaderGenerator/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.4.3) + +project(XcodeConfig C CXX) + +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/.." + "${CMAKE_CURRENT_SOURCE_DIR}/../modules" + ) + +set(LLDB_CONFIG_HEADER_INPUT + ${CMAKE_CURRENT_SOURCE_DIR}/../../include/lldb/Host/Config.h.cmake) + +include(LLDBGenerateConfig) diff --git a/cmake/modules/LLDBConfig.cmake b/cmake/modules/LLDBConfig.cmake index c40a24f056d8..609851f46e49 100644 --- a/cmake/modules/LLDBConfig.cmake +++ b/cmake/modules/LLDBConfig.cmake @@ -426,20 +426,4 @@ if ((CMAKE_SYSTEM_NAME MATCHES "Android") AND LLVM_BUILD_STATIC AND endif() find_package(Backtrace) - -include(CheckIncludeFile) -check_include_file(termios.h HAVE_TERMIOS_H) -check_include_file(sys/event.h HAVE_SYS_EVENT_H) - -# These checks exist in LLVM's configuration, so I want to match the LLVM names -# so that the check isn't duplicated, but we translate them into the LLDB names -# so that I don't have to change all the uses at the moment. -set(LLDB_CONFIG_TERMIOS_SUPPORTED ${HAVE_TERMIOS_H}) -if(NOT UNIX) - set(LLDB_DISABLE_POSIX 1) -endif() - -# This should be done at the end -configure_file( - ${LLDB_INCLUDE_ROOT}/lldb/Host/Config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/include/lldb/Host/Config.h) +include(LLDBGenerateConfig) diff --git a/cmake/modules/LLDBGenerateConfig.cmake b/cmake/modules/LLDBGenerateConfig.cmake new file mode 100644 index 000000000000..f812cf11614a --- /dev/null +++ b/cmake/modules/LLDBGenerateConfig.cmake @@ -0,0 +1,35 @@ +# This file contains all the logic for running configure-time checks + +include(CheckSymbolExists) +include(CheckIncludeFile) +include(CheckIncludeFiles) + +set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) +check_symbol_exists(ppoll poll.h HAVE_PPOLL) +set(CMAKE_REQUIRED_DEFINITIONS) +check_symbol_exists(sigaction signal.h HAVE_SIGACTION) + +check_include_file(termios.h HAVE_TERMIOS_H) +check_include_files("sys/types.h;sys/event.h" HAVE_SYS_EVENT_H) + +# These checks exist in LLVM's configuration, so I want to match the LLVM names +# so that the check isn't duplicated, but we translate them into the LLDB names +# so that I don't have to change all the uses at the moment. +set(LLDB_CONFIG_TERMIOS_SUPPORTED ${HAVE_TERMIOS_H}) +if(NOT UNIX) + set(LLDB_DISABLE_POSIX 1) +endif() + +if(NOT LLDB_CONFIG_HEADER_INPUT) + set(LLDB_CONFIG_HEADER_INPUT ${LLDB_INCLUDE_ROOT}/lldb/Host/Config.h.cmake) +endif() + +if(NOT LLDB_CONFIG_HEADER_OUTPUT) + set(LLDB_CONFIG_HEADER_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/lldb/Host/Config.h) +endif() + +# This should be done at the end +configure_file( + ${LLDB_CONFIG_HEADER_INPUT} + ${LLDB_CONFIG_HEADER_OUTPUT} + ) diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h index ca47a38a2ef5..33735bc99f60 100644 --- a/include/lldb/Core/Module.h +++ b/include/lldb/Core/Module.h @@ -614,6 +614,8 @@ public: const FileSpec &GetSymbolFileFileSpec() const { return m_symfile_spec; } + void PreloadSymbols(); + void SetSymbolFileFileSpec(const FileSpec &file); const llvm::sys::TimePoint<> &GetModificationTime() const { diff --git a/include/lldb/Core/TraceOptions.h b/include/lldb/Core/TraceOptions.h index ffa2bae7f659..e875a531e870 100644 --- a/include/lldb/Core/TraceOptions.h +++ b/include/lldb/Core/TraceOptions.h @@ -59,4 +59,4 @@ private: }; } -#endif // liblldb_TraceOptions_h_
\ No newline at end of file +#endif // liblldb_TraceOptions_h_ diff --git a/include/lldb/Core/UniqueCStringMap.h b/include/lldb/Core/UniqueCStringMap.h index 1475fdaa74d9..e8c6c7c1353e 100644 --- a/include/lldb/Core/UniqueCStringMap.h +++ b/include/lldb/Core/UniqueCStringMap.h @@ -17,10 +17,9 @@ // Other libraries and framework includes // Project includes +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/RegularExpression.h" -#include "llvm/ADT/StringRef.h" - namespace lldb_private { //---------------------------------------------------------------------- @@ -37,13 +36,17 @@ public: struct Entry { Entry() {} - Entry(llvm::StringRef cstr) : cstring(cstr), value() {} + Entry(ConstString cstr) : cstring(cstr), value() {} - Entry(llvm::StringRef cstr, const T &v) : cstring(cstr), value(v) {} + Entry(ConstString cstr, const T &v) : cstring(cstr), value(v) {} - bool operator<(const Entry &rhs) const { return cstring < rhs.cstring; } + // This is only for uniqueness, not lexicographical ordering, so we can + // just compare pointers. + bool operator<(const Entry &rhs) const { + return cstring.GetCString() < rhs.cstring.GetCString(); + } - llvm::StringRef cstring; + ConstString cstring; T value; }; @@ -52,7 +55,7 @@ public: // this map, then later call UniqueCStringMap<T>::Sort() before doing // any searches by name. //------------------------------------------------------------------ - void Append(llvm::StringRef unique_cstr, const T &value) { + void Append(ConstString unique_cstr, const T &value) { m_map.push_back(typename UniqueCStringMap<T>::Entry(unique_cstr, value)); } @@ -64,7 +67,7 @@ public: // Call this function to always keep the map sorted when putting // entries into the map. //------------------------------------------------------------------ - void Insert(llvm::StringRef unique_cstr, const T &value) { + void Insert(ConstString unique_cstr, const T &value) { typename UniqueCStringMap<T>::Entry e(unique_cstr, value); m_map.insert(std::upper_bound(m_map.begin(), m_map.end(), e), e); } @@ -87,7 +90,7 @@ public: return false; } - llvm::StringRef GetCStringAtIndexUnchecked(uint32_t idx) const { + ConstString GetCStringAtIndexUnchecked(uint32_t idx) const { return m_map[idx].cstring; } @@ -101,8 +104,8 @@ public: return m_map[idx].value; } - llvm::StringRef GetCStringAtIndex(uint32_t idx) const { - return ((idx < m_map.size()) ? m_map[idx].cstring : llvm::StringRef()); + ConstString GetCStringAtIndex(uint32_t idx) const { + return ((idx < m_map.size()) ? m_map[idx].cstring : ConstString()); } //------------------------------------------------------------------ @@ -113,7 +116,7 @@ public: // T values and only if there is a sensible failure value that can // be returned and that won't match any existing values. //------------------------------------------------------------------ - T Find(llvm::StringRef unique_cstr, T fail_value) const { + T Find(ConstString unique_cstr, T fail_value) const { Entry search_entry(unique_cstr); const_iterator end = m_map.end(); const_iterator pos = std::lower_bound(m_map.begin(), end, search_entry); @@ -131,15 +134,12 @@ public: // The caller is responsible for ensuring that the collection does // not change during while using the returned pointer. //------------------------------------------------------------------ - const Entry *FindFirstValueForName(llvm::StringRef unique_cstr) const { + const Entry *FindFirstValueForName(ConstString unique_cstr) const { Entry search_entry(unique_cstr); const_iterator end = m_map.end(); const_iterator pos = std::lower_bound(m_map.begin(), end, search_entry); - if (pos != end) { - llvm::StringRef pos_cstr = pos->cstring; - if (pos_cstr == unique_cstr) - return &(*pos); - } + if (pos != end && pos->cstring == unique_cstr) + return &(*pos); return nullptr; } @@ -164,7 +164,7 @@ public: return nullptr; } - size_t GetValues(llvm::StringRef unique_cstr, std::vector<T> &values) const { + size_t GetValues(ConstString unique_cstr, std::vector<T> &values) const { const size_t start_size = values.size(); Entry search_entry(unique_cstr); @@ -186,7 +186,7 @@ public: const_iterator pos, end = m_map.end(); for (pos = m_map.begin(); pos != end; ++pos) { - if (regex.Execute(pos->cstring)) + if (regex.Execute(pos->cstring.GetCString())) values.push_back(pos->value); } @@ -240,7 +240,7 @@ public: } } - size_t Erase(llvm::StringRef unique_cstr) { + size_t Erase(ConstString unique_cstr) { size_t num_removed = 0; Entry search_entry(unique_cstr); iterator end = m_map.end(); diff --git a/include/lldb/Host/Config.h b/include/lldb/Host/Config.h index 95d0191397b3..3fa19e77452d 100644 --- a/include/lldb/Host/Config.h +++ b/include/lldb/Host/Config.h @@ -18,6 +18,10 @@ #define HAVE_SYS_EVENT_H 1 +#define HAVE_PPOLL 0 + +#define HAVE_SIGACTION 1 + #else #error This file is only used by the Xcode build. diff --git a/include/lldb/Host/Config.h.cmake b/include/lldb/Host/Config.h.cmake index d072c1a08687..5a16425fe0a9 100644 --- a/include/lldb/Host/Config.h.cmake +++ b/include/lldb/Host/Config.h.cmake @@ -16,4 +16,8 @@ #cmakedefine01 HAVE_SYS_EVENT_H +#cmakedefine01 HAVE_PPOLL + +#cmakedefine01 HAVE_SIGACTION + #endif // #ifndef LLDB_HOST_CONFIG_H diff --git a/include/lldb/Host/MainLoop.h b/include/lldb/Host/MainLoop.h index 8aa26b63183a..79370bf8461f 100644 --- a/include/lldb/Host/MainLoop.h +++ b/include/lldb/Host/MainLoop.h @@ -10,16 +10,96 @@ #ifndef lldb_Host_MainLoop_h_ #define lldb_Host_MainLoop_h_ -#ifdef _WIN32 +#include "lldb/Host/Config.h" #include "lldb/Host/MainLoopBase.h" + +#include "llvm/ADT/DenseMap.h" + +#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H +#define SIGNAL_POLLING_UNSUPPORTED 1 +#endif + namespace lldb_private { -typedef MainLoopBase MainLoop; -} -#else -#include "lldb/Host/posix/MainLoopPosix.h" -namespace lldb_private { -typedef MainLoopPosix MainLoop; -} + +// Implementation of the MainLoopBase class. It can monitor file descriptors for +// readability using ppoll, kqueue, poll or WSAPoll. On Windows it only supports +// polling sockets, and will not work on generic file handles or pipes. On +// systems without kqueue or ppoll handling singnals is not supported. In +// addition to the common base, this class provides the ability to invoke a +// given handler when a signal is received. +// +// Since this class is primarily intended to be used for single-threaded +// processing, it does not attempt to perform any internal synchronisation and +// any concurrent accesses must be protected externally. However, it is +// perfectly legitimate to have more than one instance of this class running on +// separate threads, or even a single thread (with some limitations on signal +// monitoring). +// TODO: Add locking if this class is to be used in a multi-threaded context. +class MainLoop : public MainLoopBase { +private: + class SignalHandle; + +public: + typedef std::unique_ptr<SignalHandle> SignalHandleUP; + + ~MainLoop() override; + + ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, + const Callback &callback, + Error &error) override; + + // Listening for signals from multiple MainLoop instances is perfectly safe as + // long as they don't try to listen for the same signal. The callback function + // is invoked when the control returns to the Run() function, not when the + // hander is executed. This mean that you can treat the callback as a normal + // function and perform things which would not be safe in a signal handler. + // However, since the callback is not invoked synchronously, you cannot use + // this mechanism to handle SIGSEGV and the like. + SignalHandleUP RegisterSignal(int signo, const Callback &callback, + Error &error); + + Error Run() override; + + // This should only be performed from a callback. Do not attempt to terminate + // the processing from another thread. + // TODO: Add synchronization if we want to be terminated from another thread. + void RequestTermination() override { m_terminate_request = true; } + +protected: + void UnregisterReadObject(IOObject::WaitableHandle handle) override; + + void UnregisterSignal(int signo); + +private: + class SignalHandle { + public: + ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); } + + private: + SignalHandle(MainLoop &mainloop, int signo) + : m_mainloop(mainloop), m_signo(signo) {} + + MainLoop &m_mainloop; + int m_signo; + + friend class MainLoop; + DISALLOW_COPY_AND_ASSIGN(SignalHandle); + }; + + struct SignalInfo { + Callback callback; +#if HAVE_SIGACTION + struct sigaction old_action; #endif + bool was_blocked : 1; + }; + class RunImpl; + + llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds; + llvm::DenseMap<int, SignalInfo> m_signals; + bool m_terminate_request : 1; +}; + +} // namespace lldb_private #endif // lldb_Host_MainLoop_h_ diff --git a/include/lldb/Host/PosixApi.h b/include/lldb/Host/PosixApi.h index 23a291c401de..02324307dc9e 100644 --- a/include/lldb/Host/PosixApi.h +++ b/include/lldb/Host/PosixApi.h @@ -14,9 +14,7 @@ // to provide a minimum level of compatibility across all platforms to rely // on various posix api functionality. -#include "llvm/Support/Compiler.h" - -#if defined(LLVM_ON_WIN32) +#if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" #endif diff --git a/include/lldb/Host/Socket.h b/include/lldb/Host/Socket.h index 386133e96952..36d506281cf8 100644 --- a/include/lldb/Host/Socket.h +++ b/include/lldb/Host/Socket.h @@ -57,8 +57,7 @@ public: virtual Error Connect(llvm::StringRef name) = 0; virtual Error Listen(llvm::StringRef name, int backlog) = 0; - virtual Error Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) = 0; + virtual Error Accept(Socket *&socket) = 0; // Initialize a Tcp Socket object in listening mode. listen and accept are // implemented @@ -103,7 +102,8 @@ public: int32_t &port, Error *error_ptr); protected: - Socket(NativeSocket socket, SocketProtocol protocol, bool should_close); + Socket(SocketProtocol protocol, bool should_close, + bool m_child_process_inherit); virtual size_t Send(const void *buf, const size_t num_bytes); @@ -117,6 +117,7 @@ protected: SocketProtocol m_protocol; NativeSocket m_socket; + bool m_child_processes_inherit; }; } // namespace lldb_private diff --git a/include/lldb/Host/common/TCPSocket.h b/include/lldb/Host/common/TCPSocket.h index 2ce8d824f0a0..5b72f344019f 100644 --- a/include/lldb/Host/common/TCPSocket.h +++ b/include/lldb/Host/common/TCPSocket.h @@ -11,12 +11,16 @@ #define liblldb_TCPSocket_h_ #include "lldb/Host/Socket.h" +#include "lldb/Host/SocketAddress.h" +#include <map> namespace lldb_private { class TCPSocket : public Socket { public: - TCPSocket(NativeSocket socket, bool should_close); - TCPSocket(bool child_processes_inherit, Error &error); + TCPSocket(bool should_close, bool child_processes_inherit); + TCPSocket(NativeSocket socket, bool should_close, + bool child_processes_inherit); + ~TCPSocket() override; // returns port number or 0 if error uint16_t GetLocalPortNumber() const; @@ -37,8 +41,18 @@ public: Error Connect(llvm::StringRef name) override; Error Listen(llvm::StringRef name, int backlog) override; - Error Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&conn_socket) override; + Error Accept(Socket *&conn_socket) override; + + Error CreateSocket(int domain); + + bool IsValid() const override; + +private: + TCPSocket(NativeSocket socket, const TCPSocket &listen_socket); + + void CloseListenSockets(); + + std::map<int, SocketAddress> m_listen_sockets; }; } diff --git a/include/lldb/Host/common/UDPSocket.h b/include/lldb/Host/common/UDPSocket.h index 507c9827caf6..38524fa8f62b 100644 --- a/include/lldb/Host/common/UDPSocket.h +++ b/include/lldb/Host/common/UDPSocket.h @@ -15,19 +15,20 @@ namespace lldb_private { class UDPSocket : public Socket { public: - UDPSocket(bool child_processes_inherit, Error &error); + UDPSocket(bool should_close, bool child_processes_inherit); static Error Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket); private: - UDPSocket(NativeSocket socket); + UDPSocket(NativeSocket socket, const UDPSocket &listen_socket); size_t Send(const void *buf, const size_t num_bytes) override; Error Connect(llvm::StringRef name) override; Error Listen(llvm::StringRef name, int backlog) override; - Error Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) override; + Error Accept(Socket *&socket) override; + + Error CreateSocket(); SocketAddress m_sockaddr; }; diff --git a/include/lldb/Host/linux/AbstractSocket.h b/include/lldb/Host/linux/AbstractSocket.h index f73a287cb3f8..3b38cde05522 100644 --- a/include/lldb/Host/linux/AbstractSocket.h +++ b/include/lldb/Host/linux/AbstractSocket.h @@ -15,7 +15,7 @@ namespace lldb_private { class AbstractSocket : public DomainSocket { public: - AbstractSocket(bool child_processes_inherit, Error &error); + AbstractSocket(bool child_processes_inherit); protected: size_t GetNameOffset() const override; diff --git a/include/lldb/Host/posix/DomainSocket.h b/include/lldb/Host/posix/DomainSocket.h index 3bd4e0141336..78a3dc89828a 100644 --- a/include/lldb/Host/posix/DomainSocket.h +++ b/include/lldb/Host/posix/DomainSocket.h @@ -15,22 +15,20 @@ namespace lldb_private { class DomainSocket : public Socket { public: - DomainSocket(bool child_processes_inherit, Error &error); + DomainSocket(bool should_close, bool child_processes_inherit); Error Connect(llvm::StringRef name) override; Error Listen(llvm::StringRef name, int backlog) override; - Error Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) override; + Error Accept(Socket *&socket) override; protected: - DomainSocket(SocketProtocol protocol, bool child_processes_inherit, - Error &error); + DomainSocket(SocketProtocol protocol, bool child_processes_inherit); virtual size_t GetNameOffset() const; virtual void DeleteSocketFile(llvm::StringRef name); private: - DomainSocket(NativeSocket socket); + DomainSocket(NativeSocket socket, const DomainSocket &listen_socket); }; } diff --git a/include/lldb/Host/posix/MainLoopPosix.h b/include/lldb/Host/posix/MainLoopPosix.h deleted file mode 100644 index 21e02becf872..000000000000 --- a/include/lldb/Host/posix/MainLoopPosix.h +++ /dev/null @@ -1,104 +0,0 @@ -//===-- MainLoopPosix.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_Host_posix_MainLoopPosix_h_ -#define lldb_Host_posix_MainLoopPosix_h_ - -#include "lldb/Host/MainLoopBase.h" - -#include "llvm/ADT/DenseMap.h" - -namespace lldb_private { - -// Posix implementation of the MainLoopBase class. It can monitor file -// descriptors for -// readability using pselect. In addition to the common base, this class -// provides the ability to -// invoke a given handler when a signal is received. -// -// Since this class is primarily intended to be used for single-threaded -// processing, it does not -// attempt to perform any internal synchronisation and any concurrent accesses -// must be protected -// externally. However, it is perfectly legitimate to have more than one -// instance of this class -// running on separate threads, or even a single thread (with some limitations -// on signal -// monitoring). -// TODO: Add locking if this class is to be used in a multi-threaded context. -class MainLoopPosix : public MainLoopBase { -private: - class SignalHandle; - -public: - typedef std::unique_ptr<SignalHandle> SignalHandleUP; - - ~MainLoopPosix() override; - - ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, - const Callback &callback, - Error &error) override; - - // Listening for signals from multiple MainLoopPosix instances is perfectly - // safe as long as they - // don't try to listen for the same signal. The callback function is invoked - // when the control - // returns to the Run() function, not when the hander is executed. This means - // that you can - // treat the callback as a normal function and perform things which would not - // be safe in a - // signal handler. However, since the callback is not invoked synchronously, - // you cannot use - // this mechanism to handle SIGSEGV and the like. - SignalHandleUP RegisterSignal(int signo, const Callback &callback, - Error &error); - - Error Run() override; - - // This should only be performed from a callback. Do not attempt to terminate - // the processing - // from another thread. - // TODO: Add synchronization if we want to be terminated from another thread. - void RequestTermination() override { m_terminate_request = true; } - -protected: - void UnregisterReadObject(IOObject::WaitableHandle handle) override; - - void UnregisterSignal(int signo); - -private: - class SignalHandle { - public: - ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); } - - private: - SignalHandle(MainLoopPosix &mainloop, int signo) - : m_mainloop(mainloop), m_signo(signo) {} - - MainLoopPosix &m_mainloop; - int m_signo; - - friend class MainLoopPosix; - DISALLOW_COPY_AND_ASSIGN(SignalHandle); - }; - - struct SignalInfo { - Callback callback; - struct sigaction old_action; - bool was_blocked : 1; - }; - - llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds; - llvm::DenseMap<int, SignalInfo> m_signals; - bool m_terminate_request : 1; -}; - -} // namespace lldb_private - -#endif // lldb_Host_posix_MainLoopPosix_h_ diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h index 03564eca4b58..296c9ff2129f 100644 --- a/include/lldb/Symbol/ObjectFile.h +++ b/include/lldb/Symbol/ObjectFile.h @@ -805,9 +805,9 @@ public: bool IsInMemory() const { return m_memory_addr != LLDB_INVALID_ADDRESS; } // Strip linker annotations (such as @@VERSION) from symbol names. - virtual std::string + virtual llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const { - return symbol_name.str(); + return symbol_name; } static lldb::SymbolType GetSymbolTypeFromName( diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h index 34ae8d76e195..69110dc68cd7 100644 --- a/include/lldb/Symbol/SymbolFile.h +++ b/include/lldb/Symbol/SymbolFile.h @@ -180,6 +180,8 @@ public: uint32_t type_mask, lldb_private::TypeList &type_list) = 0; + virtual void PreloadSymbols(); + virtual lldb_private::TypeSystem * GetTypeSystemForLanguage(lldb::LanguageType language); diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h index 6a8d62cea8b7..3d24862af365 100644 --- a/include/lldb/Symbol/Symtab.h +++ b/include/lldb/Symbol/Symtab.h @@ -40,6 +40,7 @@ public: Symtab(ObjectFile *objfile); ~Symtab(); + void PreloadSymbols(); void Reserve(size_t count); Symbol *Resize(size_t count); uint32_t AddSymbol(const Symbol &symbol); diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h index 8d6fc772c887..8aa263f59254 100644 --- a/include/lldb/Target/Target.h +++ b/include/lldb/Target/Target.h @@ -82,6 +82,10 @@ public: bool SetPreferDynamicValue(lldb::DynamicValueType d); + bool GetPreloadSymbols() const; + + void SetPreloadSymbols(bool b); + bool GetDisableASLR() const; void SetDisableASLR(bool b); diff --git a/lldb.xcodeproj/project.pbxproj b/lldb.xcodeproj/project.pbxproj index 6bcd8619f0b6..e988dba59992 100644 --- a/lldb.xcodeproj/project.pbxproj +++ b/lldb.xcodeproj/project.pbxproj @@ -665,7 +665,6 @@ 26FFC19D14FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */; }; 304B2E461CAAA57B007829FE /* ClangUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */; }; 30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 3032B1B91CAAA400004BE1AB /* ClangUtil.h */; }; - 30DED5DE1B4ECB49004CC508 /* MainLoopPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */; }; 332CCB181AFF41620034D4C4 /* SBLanguageRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33E5E8411A672A240024ED68 /* StringConvert.cpp */; }; 3F8160A61AB9F7DD001DA9DF /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8160A51AB9F7DD001DA9DF /* Logging.cpp */; }; @@ -868,6 +867,8 @@ 9A0FDEA71E8EF5110086B2F5 /* RegisterContextLinux_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.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 */; }; + 9A1E595D1EB2B141002206A5 /* SBTraceOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */; }; 9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; }; 9A22A163135E30370024DDC3 /* EmulationStateARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */; }; 9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A357582116CFDEE00E8ED2F /* SBValueList.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -876,6 +877,8 @@ 9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A357672116E7B6400E8ED2F /* SBStringList.cpp */; }; 9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; }; + 9A36D24D1EB3BE7F00AAD9EA /* SBTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1E59581EB2B10D002206A5 /* SBTrace.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9A36D24E1EB3BE7F00AAD9EA /* SBTraceOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */; }; 9A77AD541E64E2760025CE04 /* RegisterInfoPOSIX_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A77AD501E64E24E0025CE04 /* RegisterInfoPOSIX_arm.cpp */; }; 9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038D117674EB0086C050 /* SBInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -978,6 +981,7 @@ B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A58723143119D50092BFBA /* SBWatchpoint.cpp */; }; B2B7CCEB15D1BD6700EEFB57 /* CommandObjectWatchpointCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEA15D1BD6600EEFB57 /* CommandObjectWatchpointCommand.cpp */; }; B2B7CCF015D1C20F00EEFB57 /* WatchpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */; }; + D67521381EA17C4200439694 /* MainLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D67521351EA17C3900439694 /* MainLoop.cpp */; }; E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D6F3F4183E7F9300194858 /* lldb-gdbserver.cpp */; }; E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E769331D1A94D18100C73337 /* lldb-server.cpp */; }; E7723D441AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E7723D421AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp */; }; @@ -2319,7 +2323,6 @@ 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = "<group>"; }; 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtil.cpp; path = source/Symbol/ClangUtil.cpp; sourceTree = "<group>"; }; 3032B1B91CAAA400004BE1AB /* ClangUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtil.h; path = include/lldb/Symbol/ClangUtil.h; sourceTree = "<group>"; }; - 30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoopPosix.cpp; sourceTree = "<group>"; }; 33064C991A5C7A330033D415 /* UriParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParser.cpp; path = source/Utility/UriParser.cpp; sourceTree = "<group>"; }; 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLanguageRuntime.h; path = include/lldb/API/SBLanguageRuntime.h; sourceTree = "<group>"; }; 33E5E8411A672A240024ED68 /* StringConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringConvert.cpp; sourceTree = "<group>"; }; @@ -2810,6 +2813,10 @@ 9A0FDE9B1E8EF5010086B2F5 /* RegisterInfos_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_mips.h; path = Utility/RegisterInfos_mips.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>"; }; + 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTraceOptions.cpp; path = source/API/SBTraceOptions.cpp; sourceTree = "<group>"; }; + 9A1E59581EB2B10D002206A5 /* SBTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTrace.h; path = include/lldb/API/SBTrace.h; sourceTree = "<group>"; }; + 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTraceOptions.h; path = include/lldb/API/SBTraceOptions.h; sourceTree = "<group>"; }; 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionARM.cpp; sourceTree = "<group>"; }; 9A22A15E135E30370024DDC3 /* EmulateInstructionARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulateInstructionARM.h; sourceTree = "<group>"; }; 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationStateARM.cpp; sourceTree = "<group>"; }; @@ -3051,6 +3058,7 @@ B2B7CCED15D1BFB700EEFB57 /* WatchpointOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WatchpointOptions.h; path = include/lldb/Breakpoint/WatchpointOptions.h; sourceTree = "<group>"; }; B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WatchpointOptions.cpp; path = source/Breakpoint/WatchpointOptions.cpp; sourceTree = "<group>"; }; B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstructionUtils.h; path = Utility/InstructionUtils.h; sourceTree = "<group>"; }; + D67521351EA17C3900439694 /* MainLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoop.cpp; sourceTree = "<group>"; }; E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteSignals.cpp; path = Utility/GDBRemoteSignals.cpp; sourceTree = "<group>"; }; E73A15A51B548EC500786197 /* GDBRemoteSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteSignals.h; path = Utility/GDBRemoteSignals.h; sourceTree = "<group>"; }; E769331D1A94D18100C73337 /* lldb-server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-server.cpp"; path = "tools/lldb-server/lldb-server.cpp"; sourceTree = "<group>"; }; @@ -4004,6 +4012,10 @@ 8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */, 4C56543419D2297A002E9C44 /* SBThreadPlan.h */, 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */, + 9A1E59581EB2B10D002206A5 /* SBTrace.h */, + 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */, + 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */, + 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */, 2617447911685869005ADD65 /* SBType.h */, 261744771168585B005ADD65 /* SBType.cpp */, 9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */, @@ -5667,7 +5679,6 @@ children = ( 2579065E1BD0488D00178368 /* DomainSocket.cpp */, 255EFF751AFABA950069F277 /* LockFilePosix.cpp */, - 30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */, AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */, 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */, 3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */, @@ -5902,6 +5913,7 @@ 69A01E1A1236C5D400C660B5 /* common */ = { isa = PBXGroup; children = ( + D67521351EA17C3900439694 /* MainLoop.cpp */, 2579065A1BD0488100178368 /* TCPSocket.cpp */, 2579065B1BD0488100178368 /* UDPSocket.cpp */, 255EFF731AFABA720069F277 /* LockFileBase.cpp */, @@ -6419,6 +6431,7 @@ 254FBBA31A9166F100BD6378 /* SBAttachInfo.h in Headers */, 26680221115FD13D008E1FE4 /* SBDefines.h in Headers */, 8CCB018219BA4E270009FD44 /* SBThreadCollection.h in Headers */, + 9A36D24D1EB3BE7F00AAD9EA /* SBTrace.h in Headers */, AF0EBBEC185941360059E52F /* SBQueue.h in Headers */, 26680222115FD13D008E1FE4 /* SBError.h in Headers */, 26680223115FD13D008E1FE4 /* SBEvent.h in Headers */, @@ -6457,6 +6470,7 @@ 941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */, 9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */, 941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */, + 9A36D24E1EB3BE7F00AAD9EA /* SBTraceOptions.h in Headers */, 23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */, 941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */, 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */, @@ -7022,6 +7036,7 @@ 23DCEA461D1C4D0F00A602B4 /* SBMemoryRegionInfo.cpp in Sources */, 26680330116005E7008E1FE4 /* SBDebugger.cpp in Sources */, 26680331116005E9008E1FE4 /* SBCommunication.cpp in Sources */, + 9A1E595D1EB2B141002206A5 /* SBTraceOptions.cpp in Sources */, 26680332116005EA008E1FE4 /* SBCommandReturnObject.cpp in Sources */, 26680333116005EC008E1FE4 /* SBCommandInterpreter.cpp in Sources */, 26680335116005EE008E1FE4 /* SBBroadcaster.cpp in Sources */, @@ -7042,6 +7057,7 @@ 261744781168585B005ADD65 /* SBType.cpp in Sources */, 9A35758E116CFE0F00E8ED2F /* SBValueList.cpp in Sources */, 9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */, + 9A1E595C1EB2B141002206A5 /* SBTrace.cpp in Sources */, 9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */, 9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */, 9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */, @@ -7292,6 +7308,7 @@ 945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */, 26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */, AF3A4AD21EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp in Sources */, + D67521381EA17C4200439694 /* MainLoop.cpp in Sources */, 2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */, AF77E0A41A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp in Sources */, 4CDB8D6D1DBA91B6006C5B13 /* LibStdcppUniquePointer.cpp in Sources */, @@ -7784,7 +7801,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 30DED5DE1B4ECB49004CC508 /* MainLoopPosix.cpp in Sources */, E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */, 26DC6A1D1337FECA00FF7998 /* lldb-platform.cpp in Sources */, E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */, diff --git a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py index 61a67dc13987..edc83bf58985 100644 --- a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py +++ b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py @@ -13,14 +13,13 @@ class SharedLibTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - def test_expr(self): - """Test that types work when defined in a shared library and forward-declared in the main executable""" + def common_test_expr(self, preload_symbols): if "clang" in self.getCompiler() and "3.4" in self.getCompilerVersion(): self.skipTest( "llvm.org/pr16214 -- clang emits partial DWARF for structures referenced via typedef") self.build() - self.common_setup() + self.common_setup(preload_symbols) # This should display correctly. self.expect( @@ -31,6 +30,18 @@ class SharedLibTestCase(TestBase): "(sub_foo)", "other_element = 3"]) + self.expect( + "expression GetMeASubFoo(my_foo_ptr)", + startstr="(sub_foo *) $") + + def test_expr(self): + """Test that types work when defined in a shared library and forward-declared in the main executable""" + self.common_test_expr(True) + + def test_expr_no_preload(self): + """Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled""" + self.common_test_expr(False) + @unittest2.expectedFailure("rdar://problem/10704639") def test_frame_variable(self): """Test that types work when defined in a shared library and forward-declared in the main executable""" @@ -54,7 +65,7 @@ class SharedLibTestCase(TestBase): self.line = line_number(self.source, '// Set breakpoint 0 here.') self.shlib_names = ["foo"] - def common_setup(self): + def common_setup(self, preload_symbols = True): # Run in synchronous mode self.dbg.SetAsync(False) @@ -62,6 +73,8 @@ class SharedLibTestCase(TestBase): target = self.dbg.CreateTarget("a.out") self.assertTrue(target, VALID_TARGET) + self.runCmd("settings set target.preload-symbols " + str(preload_symbols).lower()) + # Break inside the foo function which takes a bar_ptr argument. lldbutil.run_break_set_by_file_and_line( self, self.source, self.line, num_expected_locations=1, loc_exact=True) diff --git a/packages/Python/lldbsuite/test/make/Android.rules b/packages/Python/lldbsuite/test/make/Android.rules index 3e6a093f4bae..058401f425ad 100644 --- a/packages/Python/lldbsuite/test/make/Android.rules +++ b/packages/Python/lldbsuite/test/make/Android.rules @@ -63,6 +63,7 @@ endif GCC_TOOLCHAIN = $(NDK_ROOT)/toolchains/$(TOOLCHAIN_DIR)/prebuilt/$(HOST_TAG) OBJCOPY ?= $(GCC_TOOLCHAIN)/bin/$(TOOL_PREFIX)-objcopy +ARCHIVER ?= $(GCC_TOOLCHAIN)/bin/$(TOOL_PREFIX)-ar ifeq "$(findstring clang,$(CC))" "clang" ARCH_CFLAGS += -target $(TRIPLE) -gcc-toolchain $(GCC_TOOLCHAIN) diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py b/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py index b4e90c71721c..4e03d557b7a9 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py @@ -319,8 +319,16 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): # -exec-step can keep us in the g_MyFunction for gcc self.runCmd("-exec-finish --frame 0") self.expect("\^running") - self.expect( - "\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"30\"") + it = self.expect(["\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"30\"", + "\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"29\""]) + + if it == 1: + # Call to s_MyFunction may not follow immediately after g_MyFunction. + # There might be some instructions in between to restore caller-saved registers. + # We need to get past these instructions with a next to reach call to s_MyFunction. + self.runCmd("-exec-next --thread 1") + self.expect("\^running") + self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"30\"") # Test that -exec-step steps into s_MyFunction # (and that --frame is optional) diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index ddc9fca80671..d168474c3479 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -1432,6 +1432,22 @@ size_t Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, return sc_list.GetSize() - initial_size; } +void Module::PreloadSymbols() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + SymbolVendor * sym_vendor = GetSymbolVendor(); + if (!sym_vendor) { + return; + } + // Prime the symbol file first, since it adds symbols to the symbol table. + if (SymbolFile *symbol_file = sym_vendor->GetSymbolFile()) { + symbol_file->PreloadSymbols(); + } + // Now we can prime the symbol table. + if (Symtab * symtab = sym_vendor->GetSymtab()) { + symtab->PreloadSymbols(); + } +} + void Module::SetSymbolFileFileSpec(const FileSpec &file) { if (!file.Exists()) return; diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt index f00d67420fa3..2a73c30f8524 100644 --- a/source/Host/CMakeLists.txt +++ b/source/Host/CMakeLists.txt @@ -15,6 +15,7 @@ add_host_subdirectory(common common/HostThread.cpp common/IOObject.cpp common/LockFileBase.cpp + common/MainLoop.cpp common/MonitoringProcessLauncher.cpp common/NativeBreakpoint.cpp common/NativeBreakpointList.cpp @@ -85,7 +86,6 @@ else() posix/HostProcessPosix.cpp posix/HostThreadPosix.cpp posix/LockFilePosix.cpp - posix/MainLoopPosix.cpp posix/PipePosix.cpp posix/ProcessLauncherPosixFork.cpp ) diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp new file mode 100644 index 000000000000..8a9d4f020d5f --- /dev/null +++ b/source/Host/common/MainLoop.cpp @@ -0,0 +1,382 @@ +//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/llvm-config.h" + +#include "lldb/Host/MainLoop.h" +#include "lldb/Utility/Error.h" +#include <algorithm> +#include <cassert> +#include <cerrno> +#include <csignal> +#include <vector> +#include <time.h> + +#if HAVE_SYS_EVENT_H +#include <sys/event.h> +#elif defined(LLVM_ON_WIN32) +#include <winsock2.h> +#else +#include <poll.h> +#endif + +#ifdef LLVM_ON_WIN32 +#define POLL WSAPoll +#else +#define POLL poll +#endif + +#ifdef __ANDROID__ +#define FORCE_PSELECT +#endif + +#if SIGNAL_POLLING_UNSUPPORTED +#ifdef LLVM_ON_WIN32 +typedef int sigset_t; +typedef int siginfo_t; +#endif + +int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts, + const sigset_t *) { + int timeout = + (timeout_ts == nullptr) + ? -1 + : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000); + return POLL(fds, nfds, timeout); +} + +#endif + +using namespace lldb; +using namespace lldb_private; + +static sig_atomic_t g_signal_flags[NSIG]; + +static void SignalHandler(int signo, siginfo_t *info, void *) { + assert(signo < NSIG); + g_signal_flags[signo] = 1; +} + +class MainLoop::RunImpl { +public: + // TODO: Use llvm::Expected<T> + static std::unique_ptr<RunImpl> Create(MainLoop &loop, Error &error); + ~RunImpl(); + + Error Poll(); + + template <typename F> void ForEachReadFD(F &&f); + template <typename F> void ForEachSignal(F &&f); + +private: + MainLoop &loop; + +#if HAVE_SYS_EVENT_H + int queue_id; + std::vector<struct kevent> in_events; + struct kevent out_events[4]; + int num_events = -1; + + RunImpl(MainLoop &loop, int queue_id) : loop(loop), queue_id(queue_id) { + in_events.reserve(loop.m_read_fds.size() + loop.m_signals.size()); + } +#else + std::vector<int> signals; +#ifdef FORCE_PSELECT + fd_set read_fd_set; +#else + std::vector<struct pollfd> read_fds; +#endif + + RunImpl(MainLoop &loop) : loop(loop) { + signals.reserve(loop.m_signals.size()); + } + + sigset_t get_sigmask(); +#endif +}; + +#if HAVE_SYS_EVENT_H +MainLoop::RunImpl::~RunImpl() { + int r = close(queue_id); + assert(r == 0); + (void)r; +} +std::unique_ptr<MainLoop::RunImpl> MainLoop::RunImpl::Create(MainLoop &loop, Error &error) +{ + error.Clear(); + int queue_id = kqueue(); + if(queue_id < 0) { + error = Error(errno, eErrorTypePOSIX); + return nullptr; + } + return std::unique_ptr<RunImpl>(new RunImpl(loop, queue_id)); +} + +Error MainLoop::RunImpl::Poll() { + in_events.resize(loop.m_read_fds.size() + loop.m_signals.size()); + unsigned i = 0; + for (auto &fd : loop.m_read_fds) + EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0); + + for (const auto &sig : loop.m_signals) + EV_SET(&in_events[i++], sig.first, EVFILT_SIGNAL, EV_ADD, 0, 0, 0); + + num_events = kevent(queue_id, in_events.data(), in_events.size(), out_events, + llvm::array_lengthof(out_events), nullptr); + + if (num_events < 0) + return Error("kevent() failed with error %d\n", num_events); + return Error(); +} + +template <typename F> void MainLoop::RunImpl::ForEachReadFD(F &&f) { + assert(num_events >= 0); + for (int i = 0; i < num_events; ++i) { + f(out_events[i].ident); + if (loop.m_terminate_request) + return; + } +} +template <typename F> void MainLoop::RunImpl::ForEachSignal(F && f) {} +#else +MainLoop::RunImpl::~RunImpl() {} +std::unique_ptr<MainLoop::RunImpl> MainLoop::RunImpl::Create(MainLoop &loop, Error &error) +{ + error.Clear(); + return std::unique_ptr<RunImpl>(new RunImpl(loop)); +} + +sigset_t MainLoop::RunImpl::get_sigmask() { +#if SIGNAL_POLLING_UNSUPPORTED + return 0; +#else + sigset_t sigmask; + int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask); + assert(ret == 0); + (void) ret; + + for (const auto &sig : loop.m_signals) { + signals.push_back(sig.first); + sigdelset(&sigmask, sig.first); + } + return sigmask; +#endif +} + +#ifdef FORCE_PSELECT +Error MainLoop::RunImpl::Poll() { + signals.clear(); + + FD_ZERO(&read_fd_set); + int nfds = 0; + for (const auto &fd : loop.m_read_fds) { + FD_SET(fd.first, &read_fd_set); + nfds = std::max(nfds, fd.first + 1); + } + + sigset_t sigmask = get_sigmask(); + if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && + errno != EINTR) + return Error(errno, eErrorTypePOSIX); + + return Error(); +} + +template <typename F> void MainLoop::RunImpl::ForEachReadFD(F &&f) { + for (const auto &fd : loop.m_read_fds) { + if(!FD_ISSET(fd.first, &read_fd_set)) + continue; + + f(fd.first); + if (loop.m_terminate_request) + return; + } +} +#else +Error MainLoop::RunImpl::Poll() { + signals.clear(); + read_fds.clear(); + + sigset_t sigmask = get_sigmask(); + + for (const auto &fd : loop.m_read_fds) { + struct pollfd pfd; + pfd.fd = fd.first; + pfd.events = POLLIN; + pfd.revents = 0; + read_fds.push_back(pfd); + } + + if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 && + errno != EINTR) + return Error(errno, eErrorTypePOSIX); + + return Error(); +} + +template <typename F> void MainLoop::RunImpl::ForEachReadFD(F &&f) { + for (const auto &fd : read_fds) { + if ((fd.revents & POLLIN) == 0) + continue; + + f(fd.fd); + if (loop.m_terminate_request) + return; + } +} +#endif + +template <typename F> void MainLoop::RunImpl::ForEachSignal(F &&f) { + for (int sig : signals) { + if (g_signal_flags[sig] == 0) + continue; // No signal + g_signal_flags[sig] = 0; + f(sig); + + if (loop.m_terminate_request) + return; + } +} +#endif + +MainLoop::~MainLoop() { + assert(m_read_fds.size() == 0); + assert(m_signals.size() == 0); +} + +MainLoop::ReadHandleUP +MainLoop::RegisterReadObject(const IOObjectSP &object_sp, + const Callback &callback, Error &error) { +#ifdef LLVM_ON_WIN32 + if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) { + error.SetErrorString("MainLoop: non-socket types unsupported on Windows"); + return nullptr; + } +#endif + if (!object_sp || !object_sp->IsValid()) { + error.SetErrorString("IO object is not valid."); + return nullptr; + } + + const bool inserted = + m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; + if (!inserted) { + error.SetErrorStringWithFormat("File descriptor %d already monitored.", + object_sp->GetWaitableHandle()); + return nullptr; + } + + return CreateReadHandle(object_sp); +} + +// We shall block the signal, then install the signal handler. The signal will +// be unblocked in +// the Run() function to check for signal delivery. +MainLoop::SignalHandleUP +MainLoop::RegisterSignal(int signo, const Callback &callback, + Error &error) { +#ifdef SIGNAL_POLLING_UNSUPPORTED + error.SetErrorString("Signal polling is not supported on this platform."); + return nullptr; +#else + if (m_signals.find(signo) != m_signals.end()) { + error.SetErrorStringWithFormat("Signal %d already monitored.", signo); + return nullptr; + } + + SignalInfo info; + info.callback = callback; + struct sigaction new_action; + new_action.sa_sigaction = &SignalHandler; + new_action.sa_flags = SA_SIGINFO; + sigemptyset(&new_action.sa_mask); + sigaddset(&new_action.sa_mask, signo); + + sigset_t old_set; + if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) { + error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", + ret); + return nullptr; + } + + info.was_blocked = sigismember(&old_set, signo); + if (sigaction(signo, &new_action, &info.old_action) == -1) { + error.SetErrorToErrno(); + if (!info.was_blocked) + pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr); + return nullptr; + } + + m_signals.insert({signo, info}); + g_signal_flags[signo] = 0; + + return SignalHandleUP(new SignalHandle(*this, signo)); +#endif +} + +void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) { + bool erased = m_read_fds.erase(handle); + UNUSED_IF_ASSERT_DISABLED(erased); + assert(erased); +} + +void MainLoop::UnregisterSignal(int signo) { +#if SIGNAL_POLLING_UNSUPPORTED + Error("Signal polling is not supported on this platform."); +#else + // We undo the actions of RegisterSignal on a best-effort basis. + auto it = m_signals.find(signo); + assert(it != m_signals.end()); + + sigaction(signo, &it->second.old_action, nullptr); + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, signo); + pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, + nullptr); + + m_signals.erase(it); +#endif +} + +Error MainLoop::Run() { + m_terminate_request = false; + + Error error; + auto impl = RunImpl::Create(*this, error); + if (!impl) + return error; + + // run until termination or until we run out of things to listen to + while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { + + error = impl->Poll(); + if (error.Fail()) + return error; + + impl->ForEachSignal([&](int sig) { + auto it = m_signals.find(sig); + if (it != m_signals.end()) + it->second.callback(*this); // Do the work + }); + if (m_terminate_request) + return Error(); + + impl->ForEachReadFD([&](int fd) { + auto it = m_read_fds.find(fd); + if (it != m_read_fds.end()) + it->second(*this); // Do the work + }); + if (m_terminate_request) + return Error(); + } + return Error(); +} diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index 2a665ddacb64..d73b5d0ad073 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -18,6 +18,8 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" +#include "llvm/ADT/STLExtras.h" + #ifndef LLDB_DISABLE_POSIX #include "lldb/Host/posix/DomainSocket.h" @@ -67,9 +69,11 @@ bool IsInterrupted() { } } -Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close) +Socket::Socket(SocketProtocol protocol, bool should_close, + bool child_processes_inherit) : IOObject(eFDTypeSocket, should_close), m_protocol(protocol), - m_socket(socket) {} + m_socket(kInvalidSocketValue), + m_child_processes_inherit(child_processes_inherit) {} Socket::~Socket() { Close(); } @@ -81,14 +85,17 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, std::unique_ptr<Socket> socket_up; switch (protocol) { case ProtocolTcp: - socket_up.reset(new TCPSocket(child_processes_inherit, error)); + socket_up = + llvm::make_unique<TCPSocket>(true, child_processes_inherit); break; case ProtocolUdp: - socket_up.reset(new UDPSocket(child_processes_inherit, error)); + socket_up = + llvm::make_unique<UDPSocket>(true, child_processes_inherit); break; case ProtocolUnixDomain: #ifndef LLDB_DISABLE_POSIX - socket_up.reset(new DomainSocket(child_processes_inherit, error)); + socket_up = + llvm::make_unique<DomainSocket>(true, child_processes_inherit); #else error.SetErrorString( "Unix domain sockets are not supported on this platform."); @@ -96,7 +103,8 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, break; case ProtocolUnixAbstract: #ifdef __linux__ - socket_up.reset(new AbstractSocket(child_processes_inherit, error)); + socket_up = + llvm::make_unique<AbstractSocket>(child_processes_inherit); #else error.SetErrorString( "Abstract domain sockets are not supported on this platform."); @@ -145,7 +153,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port, return error; std::unique_ptr<TCPSocket> listen_socket( - new TCPSocket(child_processes_inherit, error)); + new TCPSocket(true, child_processes_inherit)); if (error.Fail()) return error; @@ -208,7 +216,7 @@ Error Socket::UnixDomainAccept(llvm::StringRef name, if (error.Fail()) return error; - error = listen_socket->Accept(name, child_processes_inherit, socket); + error = listen_socket->Accept(socket); return error; } @@ -240,18 +248,22 @@ Error Socket::UnixAbstractAccept(llvm::StringRef name, if (error.Fail()) return error; - error = listen_socket->Accept(name, child_processes_inherit, socket); + error = listen_socket->Accept(socket); return error; } bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port, std::string &host_str, std::string &port_str, int32_t &port, Error *error_ptr) { - static RegularExpression g_regex(llvm::StringRef("([^:]+):([0-9]+)")); + static RegularExpression g_regex( + llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)")); RegularExpression::Match regex_match(2); if (g_regex.Execute(host_and_port, ®ex_match)) { if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) && regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) { + // IPv6 addresses are wrapped in [] when specified with ports + if (host_str.front() == '[' && host_str.back() == ']') + host_str = host_str.substr(1, host_str.size() - 2); bool ok = false; port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok); if (ok && port <= UINT16_MAX) { @@ -404,12 +416,12 @@ NativeSocket Socket::CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit, Error &error) { error.Clear(); - auto socketType = type; + auto socket_type = type; #ifdef SOCK_CLOEXEC if (!child_processes_inherit) - socketType |= SOCK_CLOEXEC; + socket_type |= SOCK_CLOEXEC; #endif - auto sock = ::socket(domain, socketType, protocol); + auto sock = ::socket(domain, socket_type, protocol); if (sock == kInvalidSocketValue) SetLastError(error); diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index b41cef6ca2eb..440ae5d9027f 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -6,6 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// Note: This file is used on Darwin by debugserver, so it needs to remain as +// self contained as possible, and devoid of references to LLVM unless +// there is compelling reason. +// +//===----------------------------------------------------------------------===// #if defined(_MSC_VER) #define _WINSOCK_DEPRECATED_NO_WARNINGS @@ -227,7 +233,8 @@ bool SocketAddress::getaddrinfo(const char *host, const char *service, int ai_flags) { Clear(); - auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, ai_protocol, ai_flags); + auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, + ai_protocol, ai_flags); if (!addresses.empty()) *this = addresses[0]; return IsValid(); diff --git a/source/Host/common/TCPSocket.cpp b/source/Host/common/TCPSocket.cpp index 9a009280a904..55db4bb0c456 100644 --- a/source/Host/common/TCPSocket.cpp +++ b/source/Host/common/TCPSocket.cpp @@ -14,30 +14,57 @@ #include "lldb/Host/common/TCPSocket.h" #include "lldb/Host/Config.h" +#include "lldb/Host/MainLoop.h" #include "lldb/Utility/Log.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/raw_ostream.h" + #ifndef LLDB_DISABLE_POSIX #include <arpa/inet.h> #include <netinet/tcp.h> #include <sys/socket.h> #endif +#if defined(LLVM_ON_WIN32) +#include <winsock2.h> +#endif + +#ifdef LLVM_ON_WIN32 +#define CLOSE_SOCKET closesocket +typedef const char *set_socket_option_arg_type; +#else +#define CLOSE_SOCKET ::close +typedef const void *set_socket_option_arg_type; +#endif + using namespace lldb; using namespace lldb_private; namespace { - -const int kDomain = AF_INET; const int kType = SOCK_STREAM; } -TCPSocket::TCPSocket(NativeSocket socket, bool should_close) - : Socket(socket, ProtocolTcp, should_close) {} +TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit) + : Socket(ProtocolTcp, should_close, child_processes_inherit) {} -TCPSocket::TCPSocket(bool child_processes_inherit, Error &error) - : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, - child_processes_inherit, error), - true) {} +TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket) + : Socket(ProtocolTcp, listen_socket.m_should_close_fd, + listen_socket.m_child_processes_inherit) { + m_socket = socket; +} + +TCPSocket::TCPSocket(NativeSocket socket, bool should_close, + bool child_processes_inherit) + : Socket(ProtocolTcp, should_close, child_processes_inherit) { + m_socket = socket; +} + +TCPSocket::~TCPSocket() { CloseListenSockets(); } + +bool TCPSocket::IsValid() const { + return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0; +} // Return the port number that is being used by the socket. uint16_t TCPSocket::GetLocalPortNumber() const { @@ -46,6 +73,12 @@ uint16_t TCPSocket::GetLocalPortNumber() const { socklen_t sock_addr_len = sock_addr.GetMaxLength(); if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0) return sock_addr.GetPort(); + } else if (!m_listen_sockets.empty()) { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength(); + if (::getsockname(m_listen_sockets.begin()->first, sock_addr, + &sock_addr_len) == 0) + return sock_addr.GetPort(); } return 0; } @@ -84,9 +117,18 @@ std::string TCPSocket::GetRemoteIPAddress() const { return ""; } +Error TCPSocket::CreateSocket(int domain) { + Error error; + if (IsValid()) + error = Close(); + if (error.Fail()) + return error; + m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP, + m_child_processes_inherit, error); + return error; +} + Error TCPSocket::Connect(llvm::StringRef name) { - if (m_socket == kInvalidSocketValue) - return Error("Invalid socket"); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); if (log) @@ -99,146 +141,140 @@ Error TCPSocket::Connect(llvm::StringRef name) { if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) return error; - struct sockaddr_in sa; - ::memset(&sa, 0, sizeof(sa)); - sa.sin_family = kDomain; - sa.sin_port = htons(port); - - int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr); - - if (inet_pton_result <= 0) { - struct hostent *host_entry = gethostbyname(host_str.c_str()); - if (host_entry) - host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list); - inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr); - if (inet_pton_result <= 0) { - if (inet_pton_result == -1) - SetLastError(error); - else - error.SetErrorStringWithFormat("invalid host string: '%s'", - host_str.c_str()); + auto addresses = lldb_private::SocketAddress::GetAddressInfo( + host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + for (auto address : addresses) { + error = CreateSocket(address.GetFamily()); + if (error.Fail()) + continue; - return error; + address.SetPort(port); + + if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(), + address.GetLength())) { + CLOSE_SOCKET(GetNativeSocket()); + continue; } - } - if (-1 == - ::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) { - SetLastError(error); + SetOptionNoDelay(); + + error.Clear(); return error; } - // Keep our TCP packets coming without any delays. - SetOptionNoDelay(); - error.Clear(); + error.SetErrorString("Failed to connect port"); return error; } Error TCPSocket::Listen(llvm::StringRef name, int backlog) { - Error error; - - // enable local address reuse - SetOptionReuseAddress(); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data()); + Error error; std::string host_str; std::string port_str; int32_t port = INT32_MIN; if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) return error; - SocketAddress bind_addr; + if (host_str == "*") + host_str = "0.0.0.0"; + auto addresses = lldb_private::SocketAddress::GetAddressInfo( + host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + for (auto address : addresses) { + int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, + m_child_processes_inherit, error); + if (error.Fail()) { + error.Clear(); + continue; + } - // Only bind to the loopback address if we are expecting a connection from - // localhost to avoid any firewall issues. - const bool bind_addr_success = (host_str == "127.0.0.1") - ? bind_addr.SetToLocalhost(kDomain, port) - : bind_addr.SetToAnyAddress(kDomain, port); + // enable local address reuse + int option_value = 1; + set_socket_option_arg_type option_value_p = + reinterpret_cast<set_socket_option_arg_type>(&option_value); + ::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p, + sizeof(option_value)); - if (!bind_addr_success) { - error.SetErrorString("Failed to bind port"); - return error; - } + address.SetPort(port); + + int err = ::bind(fd, &address.sockaddr(), address.GetLength()); + if (-1 != err) + err = ::listen(fd, backlog); - int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength()); - if (err != -1) - err = ::listen(GetNativeSocket(), backlog); + if (-1 == err) { + CLOSE_SOCKET(fd); + continue; + } - if (err == -1) - SetLastError(error); + if (port == 0) { + socklen_t sa_len = address.GetLength(); + if (getsockname(fd, &address.sockaddr(), &sa_len) == 0) + port = address.GetPort(); + } + m_listen_sockets[fd] = address; + } + if (m_listen_sockets.size() == 0) + error.SetErrorString("Failed to connect port"); return error; } -Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&conn_socket) { +void TCPSocket::CloseListenSockets() { + for (auto socket : m_listen_sockets) + CLOSE_SOCKET(socket.first); + m_listen_sockets.clear(); +} + +Error TCPSocket::Accept(Socket *&conn_socket) { Error error; - std::string host_str; - std::string port_str; - int32_t port; - if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) + if (m_listen_sockets.size() == 0) { + error.SetErrorString("No open listening sockets!"); return error; + } - const sa_family_t family = kDomain; - const int socktype = kType; - const int protocol = IPPROTO_TCP; - SocketAddress listen_addr; - if (host_str.empty()) - listen_addr.SetToLocalhost(family, port); - else if (host_str.compare("*") == 0) - listen_addr.SetToAnyAddress(family, port); - else { - if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, - socktype, protocol)) { - error.SetErrorStringWithFormat("unable to resolve hostname '%s'", - host_str.c_str()); + int sock = -1; + int listen_sock = -1; + lldb_private::SocketAddress AcceptAddr; + MainLoop accept_loop; + std::vector<MainLoopBase::ReadHandleUP> handles; + for (auto socket : m_listen_sockets) { + auto fd = socket.first; + auto inherit = this->m_child_processes_inherit; + auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit)); + handles.emplace_back(accept_loop.RegisterReadObject( + io_sp, [fd, inherit, &sock, &AcceptAddr, &error, + &listen_sock](MainLoopBase &loop) { + socklen_t sa_len = AcceptAddr.GetMaxLength(); + sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit, + error); + listen_sock = fd; + loop.RequestTermination(); + }, error)); + if (error.Fail()) return error; - } } bool accept_connection = false; std::unique_ptr<TCPSocket> accepted_socket; - // Loop until we are happy with our connection while (!accept_connection) { - struct sockaddr_in accept_addr; - ::memset(&accept_addr, 0, sizeof accept_addr); -#if !(defined(__linux__) || defined(_WIN32)) - accept_addr.sin_len = sizeof accept_addr; -#endif - socklen_t accept_addr_len = sizeof accept_addr; - - int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr, - &accept_addr_len, child_processes_inherit, error); - + accept_loop.Run(); + if (error.Fail()) - break; - - bool is_same_addr = true; -#if !(defined(__linux__) || (defined(_WIN32))) - is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); -#endif - if (is_same_addr) - is_same_addr = (accept_addr.sin_addr.s_addr == - listen_addr.sockaddr_in().sin_addr.s_addr); - - if (is_same_addr || - (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) { - accept_connection = true; - accepted_socket.reset(new TCPSocket(sock, true)); - } else { - const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; - const uint8_t *listen_ip = - (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; - ::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u " - "(expecting %u.%u.%u.%u)\n", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - accepted_socket.reset(); + return error; + + lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock]; + if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) { + CLOSE_SOCKET(sock); + llvm::errs() << llvm::formatv( + "error: rejecting incoming connection from {0} (expecting {1})", + AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress()); + continue; } + accept_connection = true; + accepted_socket.reset(new TCPSocket(sock, *this)); } if (!accepted_socket) diff --git a/source/Host/common/UDPSocket.cpp b/source/Host/common/UDPSocket.cpp index 7ca62e7496ba..a32657aab0a6 100644 --- a/source/Host/common/UDPSocket.cpp +++ b/source/Host/common/UDPSocket.cpp @@ -28,13 +28,16 @@ const int kDomain = AF_INET; const int kType = SOCK_DGRAM; static const char *g_not_supported_error = "Not supported"; -} +} // namespace -UDPSocket::UDPSocket(NativeSocket socket) : Socket(socket, ProtocolUdp, true) {} +UDPSocket::UDPSocket(bool should_close, bool child_processes_inherit) + : Socket(ProtocolUdp, should_close, child_processes_inherit) {} -UDPSocket::UDPSocket(bool child_processes_inherit, Error &error) - : UDPSocket( - CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} +UDPSocket::UDPSocket(NativeSocket socket, const UDPSocket &listen_socket) + : Socket(ProtocolUdp, listen_socket.m_should_close_fd, + listen_socket.m_child_processes_inherit) { + m_socket = socket; +} size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0, @@ -42,27 +45,14 @@ size_t UDPSocket::Send(const void *buf, const size_t num_bytes) { } Error UDPSocket::Connect(llvm::StringRef name) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Listen(llvm::StringRef name, int backlog) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) { - return Error("%s", g_not_supported_error); -} - -Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) { - std::unique_ptr<UDPSocket> final_socket; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); Error error; + if (error.Fail()) + return error; + std::string host_str; std::string port_str; int32_t port = INT32_MIN; @@ -94,12 +84,11 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, for (struct addrinfo *service_info_ptr = service_info_list; service_info_ptr != nullptr; service_info_ptr = service_info_ptr->ai_next) { - auto send_fd = CreateSocket( + m_socket = Socket::CreateSocket( service_info_ptr->ai_family, service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, child_processes_inherit, error); + service_info_ptr->ai_protocol, m_child_processes_inherit, error); if (error.Success()) { - final_socket.reset(new UDPSocket(send_fd)); - final_socket->m_sockaddr = service_info_ptr; + m_sockaddr = service_info_ptr; break; } else continue; @@ -107,16 +96,17 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, ::freeaddrinfo(service_info_list); - if (!final_socket) + if (IsValid()) return error; SocketAddress bind_addr; // Only bind to the loopback address if we are expecting a connection from // localhost to avoid any firewall issues. - const bool bind_addr_success = (host_str == "127.0.0.1" || host_str == "localhost") - ? bind_addr.SetToLocalhost(kDomain, port) - : bind_addr.SetToAnyAddress(kDomain, port); + const bool bind_addr_success = + (host_str == "127.0.0.1" || host_str == "localhost") + ? bind_addr.SetToLocalhost(kDomain, port) + : bind_addr.SetToAnyAddress(kDomain, port); if (!bind_addr_success) { error.SetErrorString("Failed to get hostspec to bind for"); @@ -125,13 +115,37 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, bind_addr.SetPort(0); // Let the source port # be determined dynamically - err = ::bind(final_socket->GetNativeSocket(), bind_addr, bind_addr.GetLength()); - - struct sockaddr_in source_info; - socklen_t address_len = sizeof (struct sockaddr_in); - err = ::getsockname(final_socket->GetNativeSocket(), (struct sockaddr *) &source_info, &address_len); + err = ::bind(m_socket, bind_addr, bind_addr.GetLength()); - socket = final_socket.release(); error.Clear(); return error; } + +Error UDPSocket::Listen(llvm::StringRef name, int backlog) { + return Error("%s", g_not_supported_error); +} + +Error UDPSocket::Accept(Socket *&socket) { + return Error("%s", g_not_supported_error); +} + +Error UDPSocket::CreateSocket() { + Error error; + if (IsValid()) + error = Close(); + if (error.Fail()) + return error; + m_socket = + Socket::CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error); + return error; +} + +Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, + Socket *&socket) { + std::unique_ptr<UDPSocket> final_socket( + new UDPSocket(true, child_processes_inherit)); + Error error = final_socket->Connect(name); + if (!error.Fail()) + socket = final_socket.release(); + return error; +} diff --git a/source/Host/linux/AbstractSocket.cpp b/source/Host/linux/AbstractSocket.cpp index b6b59ae403db..2d6f6adaf1ef 100644 --- a/source/Host/linux/AbstractSocket.cpp +++ b/source/Host/linux/AbstractSocket.cpp @@ -14,8 +14,8 @@ using namespace lldb; using namespace lldb_private; -AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error) - : DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) {} +AbstractSocket::AbstractSocket(bool child_processes_inherit) + : DomainSocket(ProtocolUnixAbstract, child_processes_inherit) {} size_t AbstractSocket::GetNameOffset() const { return 1; } diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index a3ac36558e32..befc847d8a86 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -218,7 +218,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, // assume we don't own it. std::unique_ptr<TCPSocket> tcp_socket; - tcp_socket.reset(new TCPSocket(fd, false)); + tcp_socket.reset(new TCPSocket(fd, false, false)); // Try and get a socket option from this file descriptor to // see if this is a socket and set m_is_socket accordingly. int resuse; @@ -720,7 +720,7 @@ ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s, listening_socket_up.reset(socket); socket = nullptr; - error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); + error = listening_socket_up->Accept(socket); listening_socket_up.reset(); if (error_ptr) *error_ptr = error; diff --git a/source/Host/posix/DomainSocket.cpp b/source/Host/posix/DomainSocket.cpp index 538979df2b6b..33c71268c2e3 100644 --- a/source/Host/posix/DomainSocket.cpp +++ b/source/Host/posix/DomainSocket.cpp @@ -56,19 +56,21 @@ bool SetSockAddr(llvm::StringRef name, const size_t name_offset, return true; } -} - -DomainSocket::DomainSocket(NativeSocket socket) - : Socket(socket, ProtocolUnixDomain, true) {} +} // namespace -DomainSocket::DomainSocket(bool child_processes_inherit, Error &error) - : DomainSocket( - CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {} +DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit) + : Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {} DomainSocket::DomainSocket(SocketProtocol protocol, - bool child_processes_inherit, Error &error) - : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), - protocol, true) {} + bool child_processes_inherit) + : Socket(protocol, true, child_processes_inherit) {} + +DomainSocket::DomainSocket(NativeSocket socket, + const DomainSocket &listen_socket) + : Socket(ProtocolUnixDomain, listen_socket.m_should_close_fd, + listen_socket.m_child_processes_inherit) { + m_socket = socket; +} Error DomainSocket::Connect(llvm::StringRef name) { sockaddr_un saddr_un; @@ -77,6 +79,9 @@ Error DomainSocket::Connect(llvm::StringRef name) { return Error("Failed to set socket address"); Error error; + m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error); + if (error.Fail()) + return error; if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0) SetLastError(error); @@ -93,6 +98,9 @@ Error DomainSocket::Listen(llvm::StringRef name, int backlog) { DeleteSocketFile(name); Error error; + m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error); + if (error.Fail()) + return error; if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0) if (::listen(GetNativeSocket(), backlog) == 0) @@ -102,13 +110,12 @@ Error DomainSocket::Listen(llvm::StringRef name, int backlog) { return error; } -Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, - Socket *&socket) { +Error DomainSocket::Accept(Socket *&socket) { Error error; auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, - child_processes_inherit, error); + m_child_processes_inherit, error); if (error.Success()) - socket = new DomainSocket(conn_fd); + socket = new DomainSocket(conn_fd, *this); return error; } diff --git a/source/Host/posix/MainLoopPosix.cpp b/source/Host/posix/MainLoopPosix.cpp deleted file mode 100644 index a73187e730f0..000000000000 --- a/source/Host/posix/MainLoopPosix.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//===-- MainLoopPosix.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/posix/MainLoopPosix.h" -#include "lldb/Utility/Error.h" -#include <algorithm> -#include <cassert> -#include <cerrno> -#include <csignal> -#include <sys/select.h> -#include <vector> - -using namespace lldb; -using namespace lldb_private; - -static sig_atomic_t g_signal_flags[NSIG]; - -static void SignalHandler(int signo, siginfo_t *info, void *) { - assert(signo < NSIG); - g_signal_flags[signo] = 1; -} - -MainLoopPosix::~MainLoopPosix() { - assert(m_read_fds.size() == 0); - assert(m_signals.size() == 0); -} - -MainLoopPosix::ReadHandleUP -MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, - const Callback &callback, Error &error) { - if (!object_sp || !object_sp->IsValid()) { - error.SetErrorString("IO object is not valid."); - return nullptr; - } - - const bool inserted = - m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; - if (!inserted) { - error.SetErrorStringWithFormat("File descriptor %d already monitored.", - object_sp->GetWaitableHandle()); - return nullptr; - } - - return CreateReadHandle(object_sp); -} - -// We shall block the signal, then install the signal handler. The signal will -// be unblocked in -// the Run() function to check for signal delivery. -MainLoopPosix::SignalHandleUP -MainLoopPosix::RegisterSignal(int signo, const Callback &callback, - Error &error) { - if (m_signals.find(signo) != m_signals.end()) { - error.SetErrorStringWithFormat("Signal %d already monitored.", signo); - return nullptr; - } - - SignalInfo info; - info.callback = callback; - struct sigaction new_action; - new_action.sa_sigaction = &SignalHandler; - new_action.sa_flags = SA_SIGINFO; - sigemptyset(&new_action.sa_mask); - sigaddset(&new_action.sa_mask, signo); - - sigset_t old_set; - if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) { - error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", - ret); - return nullptr; - } - - info.was_blocked = sigismember(&old_set, signo); - if (sigaction(signo, &new_action, &info.old_action) == -1) { - error.SetErrorToErrno(); - if (!info.was_blocked) - pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr); - return nullptr; - } - - m_signals.insert({signo, info}); - g_signal_flags[signo] = 0; - - return SignalHandleUP(new SignalHandle(*this, signo)); -} - -void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { - bool erased = m_read_fds.erase(handle); - UNUSED_IF_ASSERT_DISABLED(erased); - assert(erased); -} - -void MainLoopPosix::UnregisterSignal(int signo) { - // We undo the actions of RegisterSignal on a best-effort basis. - auto it = m_signals.find(signo); - assert(it != m_signals.end()); - - sigaction(signo, &it->second.old_action, nullptr); - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, signo); - pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, - nullptr); - - m_signals.erase(it); -} - -Error MainLoopPosix::Run() { - std::vector<int> signals; - sigset_t sigmask; - std::vector<int> read_fds; - fd_set read_fd_set; - m_terminate_request = false; - - // run until termination or until we run out of things to listen to - while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { - // To avoid problems with callbacks changing the things we're supposed to - // listen to, we - // will store the *real* list of events separately. - signals.clear(); - read_fds.clear(); - FD_ZERO(&read_fd_set); - int nfds = 0; - - if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask)) - return Error("pthread_sigmask failed with error %d\n", ret); - - for (const auto &fd : m_read_fds) { - read_fds.push_back(fd.first); - FD_SET(fd.first, &read_fd_set); - nfds = std::max(nfds, fd.first + 1); - } - - for (const auto &sig : m_signals) { - signals.push_back(sig.first); - sigdelset(&sigmask, sig.first); - } - - if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == - -1 && - errno != EINTR) - return Error(errno, eErrorTypePOSIX); - - for (int sig : signals) { - if (g_signal_flags[sig] == 0) - continue; // No signal - g_signal_flags[sig] = 0; - - auto it = m_signals.find(sig); - if (it == m_signals.end()) - continue; // Signal must have gotten unregistered in the meantime - - it->second.callback(*this); // Do the work - - if (m_terminate_request) - return Error(); - } - - for (int fd : read_fds) { - if (!FD_ISSET(fd, &read_fd_set)) - continue; // Not ready - - auto it = m_read_fds.find(fd); - if (it == m_read_fds.end()) - continue; // File descriptor must have gotten unregistered in the - // meantime - - it->second(*this); // Do the work - - if (m_terminate_request) - return Error(); - } - } - return Error(); -} diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index de27f7be30d3..8703bc97f06e 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -645,8 +645,8 @@ void CommandInterpreter::LoadCommandDictionary() { "gdb-remote [<hostname>:]<portnum>", 2, 0, false)); if (connect_gdb_remote_cmd_ap.get()) { if (connect_gdb_remote_cmd_ap->AddRegexCommand( - "^([^:]+:[[:digit:]]+)$", - "process connect --plugin gdb-remote connect://%1") && + "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$", + "process connect --plugin gdb-remote connect://%1:%2") && connect_gdb_remote_cmd_ap->AddRegexCommand( "^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) { diff --git a/source/Interpreter/OptionValueEnumeration.cpp b/source/Interpreter/OptionValueEnumeration.cpp index d3899677ba53..2bff0bdcec37 100644 --- a/source/Interpreter/OptionValueEnumeration.cpp +++ b/source/Interpreter/OptionValueEnumeration.cpp @@ -37,7 +37,7 @@ void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx, const size_t count = m_enumerations.GetSize(); for (size_t i = 0; i < count; ++i) { if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) { - strm.PutCString(m_enumerations.GetCStringAtIndex(i)); + strm.PutCString(m_enumerations.GetCStringAtIndex(i).GetStringRef()); return; } } @@ -58,8 +58,7 @@ Error OptionValueEnumeration::SetValueFromString(llvm::StringRef value, case eVarSetOperationAssign: { ConstString const_enumerator_name(value.trim()); const EnumerationMapEntry *enumerator_entry = - m_enumerations.FindFirstValueForName( - const_enumerator_name.GetStringRef()); + m_enumerations.FindFirstValueForName(const_enumerator_name); if (enumerator_entry) { m_current_value = enumerator_entry->value.value; NotifyValueChanged(); @@ -69,10 +68,10 @@ Error OptionValueEnumeration::SetValueFromString(llvm::StringRef value, const size_t count = m_enumerations.GetSize(); if (count) { error_strm.Printf(", valid values are: %s", - m_enumerations.GetCStringAtIndex(0).str().c_str()); + m_enumerations.GetCStringAtIndex(0).GetCString()); for (size_t i = 1; i < count; ++i) { error_strm.Printf(", %s", - m_enumerations.GetCStringAtIndex(i).str().c_str()); + m_enumerations.GetCStringAtIndex(i).GetCString()); } } error.SetErrorString(error_strm.GetString()); @@ -99,7 +98,7 @@ void OptionValueEnumeration::SetEnumerations( ConstString const_enumerator_name(enumerators[i].string_value); EnumeratorInfo enumerator_info = {enumerators[i].value, enumerators[i].usage}; - m_enumerations.Append(const_enumerator_name.GetStringRef(), + m_enumerations.Append(const_enumerator_name, enumerator_info); } m_enumerations.Sort(); @@ -119,14 +118,14 @@ size_t OptionValueEnumeration::AutoComplete( const uint32_t num_enumerators = m_enumerations.GetSize(); if (!s.empty()) { for (size_t i = 0; i < num_enumerators; ++i) { - llvm::StringRef name = m_enumerations.GetCStringAtIndex(i); + llvm::StringRef name = m_enumerations.GetCStringAtIndex(i).GetStringRef(); if (name.startswith(s)) matches.AppendString(name); } } else { // only suggest "true" or "false" by default for (size_t i = 0; i < num_enumerators; ++i) - matches.AppendString(m_enumerations.GetCStringAtIndex(i)); + matches.AppendString(m_enumerations.GetCStringAtIndex(i).GetStringRef()); } return matches.GetSize(); } diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp index 10370c2f667f..732769f6e6df 100644 --- a/source/Interpreter/OptionValueProperties.cpp +++ b/source/Interpreter/OptionValueProperties.cpp @@ -59,7 +59,7 @@ void OptionValueProperties::Initialize(const PropertyDefinition *defs) { for (size_t i = 0; defs[i].name; ++i) { Property property(defs[i]); assert(property.IsValid()); - m_name_to_index.Append(property.GetName(), m_properties.size()); + m_name_to_index.Append(ConstString(property.GetName()), m_properties.size()); property.GetValue()->SetParent(shared_from_this()); m_properties.push_back(property); } @@ -78,7 +78,7 @@ void OptionValueProperties::AppendProperty(const ConstString &name, bool is_global, const OptionValueSP &value_sp) { Property property(name, desc, is_global, value_sp); - m_name_to_index.Append(name.GetStringRef(), m_properties.size()); + m_name_to_index.Append(name, m_properties.size()); m_properties.push_back(property); value_sp->SetParent(shared_from_this()); m_name_to_index.Sort(); @@ -108,7 +108,7 @@ OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx, const ConstString &key, bool will_modify) const { lldb::OptionValueSP value_sp; - size_t idx = m_name_to_index.Find(key.GetStringRef(), SIZE_MAX); + size_t idx = m_name_to_index.Find(key, SIZE_MAX); if (idx < m_properties.size()) value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue(); return value_sp; @@ -218,7 +218,7 @@ Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx, uint32_t OptionValueProperties::GetPropertyIndex(const ConstString &name) const { - return m_name_to_index.Find(name.GetStringRef(), SIZE_MAX); + return m_name_to_index.Find(name, SIZE_MAX); } const Property * @@ -227,7 +227,7 @@ OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx, const ConstString &name) const { return GetPropertyAtIndex( exe_ctx, will_modify, - m_name_to_index.Find(name.GetStringRef(), SIZE_MAX)); + m_name_to_index.Find(name, SIZE_MAX)); } const Property *OptionValueProperties::GetPropertyAtIndex( diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index fe42a5ed9214..1ae9418e4d9c 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -271,144 +271,6 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier( return false; } -class CPPRuntimeEquivalents { -public: - CPPRuntimeEquivalents() { - m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, " - "std::allocator<char> >") - .GetStringRef(), - ConstString("basic_string<char>")); - - // these two (with a prefixed std::) occur when c++stdlib string class - // occurs as a template argument in some STL container - m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, " - "std::allocator<char> >") - .GetStringRef(), - ConstString("std::basic_string<char>")); - - m_impl.Sort(); - } - - void Add(ConstString &type_name, ConstString &type_equivalent) { - m_impl.Insert(type_name.GetStringRef(), type_equivalent); - } - - uint32_t FindExactMatches(ConstString &type_name, - std::vector<ConstString> &equivalents) { - uint32_t count = 0; - - for (ImplData match = - m_impl.FindFirstValueForName(type_name.GetStringRef()); - match != nullptr; match = m_impl.FindNextValueForName(match)) { - equivalents.push_back(match->value); - count++; - } - - return count; - } - - // partial matches can occur when a name with equivalents is a template - // argument. - // e.g. we may have "class Foo" be a match for "struct Bar". if we have a - // typename - // such as "class Templatized<class Foo, Anything>" we want this to be - // replaced with - // "class Templatized<struct Bar, Anything>". Since partial matching is time - // consuming - // once we get a partial match, we add it to the exact matches list for faster - // retrieval - uint32_t FindPartialMatches(ConstString &type_name, - std::vector<ConstString> &equivalents) { - uint32_t count = 0; - - llvm::StringRef type_name_cstr = type_name.GetStringRef(); - - size_t items_count = m_impl.GetSize(); - - for (size_t item = 0; item < items_count; item++) { - llvm::StringRef key_cstr = m_impl.GetCStringAtIndex(item); - if (type_name_cstr.contains(key_cstr)) { - count += AppendReplacements(type_name_cstr, key_cstr, equivalents); - } - } - - return count; - } - -private: - std::string &replace(std::string &target, std::string &pattern, - std::string &with) { - size_t pos; - size_t pattern_len = pattern.size(); - - while ((pos = target.find(pattern)) != std::string::npos) - target.replace(pos, pattern_len, with); - - return target; - } - - uint32_t AppendReplacements(llvm::StringRef original, - llvm::StringRef matching_key, - std::vector<ConstString> &equivalents) { - std::string matching_key_str(matching_key); - ConstString original_const(original); - - uint32_t count = 0; - - for (ImplData match = m_impl.FindFirstValueForName(matching_key); - match != nullptr; match = m_impl.FindNextValueForName(match)) { - std::string target(original); - std::string equiv_class(match->value.AsCString()); - - replace(target, matching_key_str, equiv_class); - - ConstString target_const(target.c_str()); - -// you will most probably want to leave this off since it might make this map -// grow indefinitely -#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW - Add(original_const, target_const); -#endif - equivalents.push_back(target_const); - - count++; - } - - return count; - } - - typedef UniqueCStringMap<ConstString> Impl; - typedef const Impl::Entry *ImplData; - Impl m_impl; -}; - -static CPPRuntimeEquivalents &GetEquivalentsMap() { - static CPPRuntimeEquivalents g_equivalents_map; - return g_equivalents_map; -} - -uint32_t -CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, - std::vector<ConstString> &equivalents) { - uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents); - - bool might_have_partials = - (count == 0) // if we have a full name match just use it - && (strchr(type_name.AsCString(), '<') != - nullptr // we should only have partial matches when templates are - // involved, check that we have - && strchr(type_name.AsCString(), '>') != nullptr); // angle brackets - // in the type_name - // before trying to - // scan for partial - // matches - - if (might_have_partials) - count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents); - - return count; -} - /// Given a mangled function `mangled`, replace all the primitive function type /// arguments of `search` with type `replace`. static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled, diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index 056cced2808a..7380ef321305 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -119,18 +119,6 @@ public: llvm::StringRef &context, llvm::StringRef &identifier); - // in some cases, compilers will output different names for one same type. - // when that happens, it might be impossible - // to construct SBType objects for a valid type, because the name that is - // available is not the same as the name that - // can be used as a search key in FindTypes(). the equivalents map here is - // meant to return possible alternative names - // for a type through which a search can be conducted. Currently, this is only - // enabled for C++ but can be extended - // to ObjC or other languages if necessary - static uint32_t FindEquivalentNames(ConstString type_name, - std::vector<ConstString> &equivalents); - // Given a mangled function name, calculates some alternative manglings since // the compiler mangling may not line up with the symbol we are expecting static uint32_t diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index 50d4510ec5f9..293d64075921 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -219,6 +219,7 @@ size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: CalculateNumChildren() { static ConstString g___pair3_("__pair3_"); static ConstString g___first_("__first_"); + static ConstString g___value_("__value_"); if (m_count != UINT32_MAX) return m_count; @@ -227,7 +228,22 @@ size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd:: ValueObjectSP m_item(m_tree->GetChildMemberWithName(g___pair3_, true)); if (!m_item) return 0; - m_item = m_item->GetChildMemberWithName(g___first_, true); + + switch (m_item->GetCompilerType().GetNumDirectBaseClasses()) { + case 1: + // Assume a pre llvm r300140 __compressed_pair implementation: + m_item = m_item->GetChildMemberWithName(g___first_, true); + break; + case 2: { + // Assume a post llvm r300140 __compressed_pair implementation: + ValueObjectSP first_elem_parent = m_item->GetChildAtIndex(0, true); + m_item = first_elem_parent->GetChildMemberWithName(g___value_, true); + break; + } + default: + return false; + } + if (!m_item) return 0; m_count = m_item->GetValueAsUnsigned(0); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index c3566b7c6bfb..526bae6900f5 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -94,9 +94,30 @@ lldb::ValueObjectSP lldb_private::formatters:: node_sp->GetChildMemberWithName(ConstString("__hash_"), true); if (!hash_sp || !value_sp) { if (!m_element_type) { - auto first_sp = m_backend.GetChildAtNamePath({ConstString("__table_"), - ConstString("__p1_"), - ConstString("__first_")}); + auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"), + ConstString("__p1_")}); + if (!p1_sp) + return nullptr; + + ValueObjectSP first_sp = nullptr; + switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) { + case 1: + // Assume a pre llvm r300140 __compressed_pair implementation: + first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"), + true); + break; + case 2: { + // Assume a post llvm r300140 __compressed_pair implementation: + ValueObjectSP first_elem_parent_sp = + p1_sp->GetChildAtIndex(0, true); + first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"), + true); + break; + } + default: + return nullptr; + } + if (!first_sp) return nullptr; m_element_type = first_sp->GetCompilerType(); @@ -152,22 +173,39 @@ bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd:: m_backend.GetChildMemberWithName(ConstString("__table_"), true); if (!table_sp) return false; - ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath( - {ConstString("__p2_"), ConstString("__first_")}); + + ValueObjectSP p2_sp = table_sp->GetChildMemberWithName( + ConstString("__p2_"), true); + ValueObjectSP num_elements_sp = nullptr; + llvm::SmallVector<ConstString, 3> next_path; + switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) { + case 1: + // Assume a pre llvm r300140 __compressed_pair implementation: + num_elements_sp = p2_sp->GetChildMemberWithName( + ConstString("__first_"), true); + next_path.append({ConstString("__p1_"), ConstString("__first_"), + ConstString("__next_")}); + break; + case 2: { + // Assume a post llvm r300140 __compressed_pair implementation: + ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true); + num_elements_sp = first_elem_parent->GetChildMemberWithName( + ConstString("__value_"), true); + next_path.append({ConstString("__p1_"), ConstString("__value_"), + ConstString("__next_")}); + break; + } + default: + return false; + } + if (!num_elements_sp) return false; m_num_elements = num_elements_sp->GetValueAsUnsigned(0); - m_tree = - table_sp - ->GetChildAtNamePath({ConstString("__p1_"), ConstString("__first_"), - ConstString("__next_")}) - .get(); + m_tree = table_sp->GetChildAtNamePath(next_path).get(); if (m_num_elements > 0) m_next_element = - table_sp - ->GetChildAtNamePath({ConstString("__p1_"), ConstString("__first_"), - ConstString("__next_")}) - .get(); + table_sp->GetChildAtNamePath(next_path).get(); return false; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 2843201e2ed9..96d7e51deba4 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -127,8 +127,25 @@ bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() { m_backend.GetChildMemberWithName(ConstString("__end_cap_"), true)); if (!data_type_finder_sp) return false; - data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName( + + switch (data_type_finder_sp->GetCompilerType().GetNumDirectBaseClasses()) { + case 1: + // Assume a pre llvm r300140 __compressed_pair implementation: + data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName( ConstString("__first_"), true); + break; + case 2: { + // Assume a post llvm r300140 __compressed_pair implementation: + ValueObjectSP first_elem_parent_sp = + data_type_finder_sp->GetChildAtIndex(0, true); + data_type_finder_sp = first_elem_parent_sp->GetChildMemberWithName( + ConstString("__value_"), true); + break; + } + default: + return false; + } + if (!data_type_finder_sp) return false; m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 07b4ae5e0add..e99fd74a352f 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -355,9 +355,14 @@ public: } } + clang::IdentifierInfo **identifier_infos = selector_components.data(); + if (!identifier_infos) { + return NULL; + } + clang::Selector sel = ast_ctx.Selectors.getSelector( is_zero_argument ? 0 : selector_components.size(), - selector_components.data()); + identifier_infos); clang::QualType ret_type = ClangUtil::GetQualType(type_realizer_sp->RealizeType( diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index b74da3300170..928157516808 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -158,7 +158,7 @@ size_t ObjectContainerBSDArchive::Archive::ParseObjects() { size_t obj_idx = m_objects.size(); m_objects.push_back(obj); // Insert all of the C strings out of order for now... - m_object_name_to_index_map.Append(obj.ar_name.GetStringRef(), obj_idx); + m_object_name_to_index_map.Append(obj.ar_name, obj_idx); offset += obj.ar_file_size; obj.Clear(); } while (data.ValidOffset(offset)); @@ -174,8 +174,7 @@ ObjectContainerBSDArchive::Archive::FindObject( const ConstString &object_name, const llvm::sys::TimePoint<> &object_mod_time) { const ObjectNameToIndexMap::Entry *match = - m_object_name_to_index_map.FindFirstValueForName( - object_name.GetStringRef()); + m_object_name_to_index_map.FindFirstValueForName(object_name); if (match) { if (object_mod_time != llvm::sys::TimePoint<>()) { const uint64_t object_date = llvm::sys::toTimeT(object_mod_time); diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 6e2001b21630..0720cca27341 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1808,10 +1808,10 @@ DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) { segment_header->p_filesz); } -std::string +llvm::StringRef ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const { size_t pos = symbol_name.find('@'); - return symbol_name.substr(0, pos).str(); + return symbol_name.substr(0, pos); } //---------------------------------------------------------------------- @@ -2418,7 +2418,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, .emplace(sect_name.GetCString(), module_section_list->FindSectionByName(sect_name)) .first; - if (section_it->second && section_it->second->GetFileSize()) + if (section_it->second) symbol_section_sp = section_it->second; } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 98bd9abb1932..9b2d58b7be82 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -152,7 +152,7 @@ public: // Returns segment data for the given index. lldb_private::DataExtractor GetSegmentDataByIndex(lldb::user_id_t id); - std::string + llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override; private: diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index 0c5e478d470e..034518c1d2e3 100644 --- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -67,7 +67,7 @@ static Error DeleteForwardPortWithAdb(uint16_t local_port, static Error FindUnusedPort(uint16_t &port) { Error error; - std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error)); + std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(true, false)); if (error.Fail()) return error; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 1d8b759d2fa8..8aec35d09ce5 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3900,10 +3900,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (src_name) { ConstString src_const_name(src_name); if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0)) - src_name_to_die_artificial.Append(src_const_name.GetStringRef(), - src_die); + src_name_to_die_artificial.Append(src_const_name, src_die); else - src_name_to_die.Append(src_const_name.GetStringRef(), src_die); + src_name_to_die.Append(src_const_name, src_die); } } } @@ -3920,10 +3919,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (dst_name) { ConstString dst_const_name(dst_name); if (dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0)) - dst_name_to_die_artificial.Append(dst_const_name.GetStringRef(), - dst_die); + dst_name_to_die_artificial.Append(dst_const_name, dst_die); else - dst_name_to_die.Append(dst_const_name.GetStringRef(), dst_die); + dst_name_to_die.Append(dst_const_name, dst_die); } } } @@ -4036,7 +4034,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( src_name_to_die.Sort(); for (idx = 0; idx < dst_size; ++idx) { - llvm::StringRef dst_name = dst_name_to_die.GetCStringAtIndex(idx); + ConstString dst_name = dst_name_to_die.GetCStringAtIndex(idx); dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); src_die = src_name_to_die.Find(dst_name, DWARFDIE()); @@ -4091,7 +4089,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( dst_name_to_die_artificial.Sort(); for (idx = 0; idx < src_size_artificial; ++idx) { - llvm::StringRef src_name_artificial = + ConstString src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx); src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked(idx); dst_die = @@ -4135,13 +4133,13 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( if (dst_size_artificial) { for (idx = 0; idx < dst_size_artificial; ++idx) { - llvm::StringRef dst_name_artificial = + ConstString dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx); if (log) log->Printf("warning: need to create artificial method for 0x%8.8x for " "method '%s'", - dst_die.GetOffset(), dst_name_artificial.str().c_str()); + dst_die.GetOffset(), dst_name_artificial.GetCString()); failures.Append(dst_die); } diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index f5f979caa38e..c97680eda0fe 100644 --- a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -28,11 +28,11 @@ void NameToDIE::Finalize() { } void NameToDIE::Insert(const ConstString &name, const DIERef &die_ref) { - m_map.Append(name.GetStringRef(), die_ref); + m_map.Append(name, die_ref); } size_t NameToDIE::Find(const ConstString &name, DIEArray &info_array) const { - return m_map.GetValues(name.GetStringRef(), info_array); + return m_map.GetValues(name, info_array); } size_t NameToDIE::Find(const RegularExpression ®ex, @@ -55,15 +55,15 @@ size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset, void NameToDIE::Dump(Stream *s) { const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { - llvm::StringRef cstr = m_map.GetCStringAtIndex(i); + ConstString cstr = m_map.GetCStringAtIndex(i); const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i); - s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", (const void *)cstr.data(), - die_ref.cu_offset, die_ref.die_offset, cstr.str().c_str()); + s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", (const void *)cstr.GetCString(), + die_ref.cu_offset, die_ref.die_offset, cstr.GetCString()); } } void NameToDIE::ForEach( - std::function<bool(llvm::StringRef name, const DIERef &die_ref)> const + std::function<bool(ConstString name, const DIERef &die_ref)> const &callback) const { const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/source/Plugins/SymbolFile/DWARF/NameToDIE.h index e3fe321338a2..bba44fda3c04 100644 --- a/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -43,7 +43,8 @@ public: DIEArray &info_array) const; void - ForEach(std::function<bool(llvm::StringRef name, const DIERef &die_ref)> const + ForEach(std::function<bool(lldb_private::ConstString name, + const DIERef &die_ref)> const &callback) const; protected: diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 973b5ef9fb46..8c2fc3d3aa42 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1917,6 +1917,12 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, return sc_list.GetSize() - prev_size; } +void SymbolFileDWARF::PreloadSymbols() { + std::lock_guard<std::recursive_mutex> guard( + GetObjectFile()->GetModule()->GetMutex()); + Index(); +} + void SymbolFileDWARF::Index() { if (m_indexed) return; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 14b29fa44fa3..9b1eb1d76fea 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -226,6 +226,8 @@ public: const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; + void PreloadSymbols() override; + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp index 6ad353099bc5..8e2576aaec95 100644 --- a/source/Symbol/ClangASTContext.cpp +++ b/source/Symbol/ClangASTContext.cpp @@ -378,10 +378,9 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. - if (IK == IK_Asm) { + if (IK.getLanguage() == InputKind::Asm) { Opts.AsmPreprocessor = 1; - } else if (IK == IK_ObjC || IK == IK_ObjCXX || IK == IK_PreprocessedObjC || - IK == IK_PreprocessedObjCXX) { + } else if (IK.isObjectiveC()) { Opts.ObjC1 = Opts.ObjC2 = 1; } @@ -389,30 +388,24 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. - switch (IK) { - case IK_None: - case IK_AST: - case IK_LLVM_IR: - case IK_RenderScript: + switch (IK.getLanguage()) { + case InputKind::Unknown: + case InputKind::LLVM_IR: + case InputKind::RenderScript: llvm_unreachable("Invalid input kind!"); - case IK_OpenCL: - LangStd = LangStandard::lang_opencl; + case InputKind::OpenCL: + LangStd = LangStandard::lang_opencl10; break; - case IK_CUDA: - case IK_PreprocessedCuda: + case InputKind::CUDA: LangStd = LangStandard::lang_cuda; break; - case IK_Asm: - case IK_C: - case IK_PreprocessedC: - case IK_ObjC: - case IK_PreprocessedObjC: + case InputKind::Asm: + case InputKind::C: + case InputKind::ObjC: LangStd = LangStandard::lang_gnu99; break; - case IK_CXX: - case IK_PreprocessedCXX: - case IK_ObjCXX: - case IK_PreprocessedObjCXX: + case InputKind::CXX: + case InputKind::ObjCXX: LangStd = LangStandard::lang_gnucxx98; break; } @@ -432,7 +425,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { Opts.WChar = true; // OpenCL has some additional defaults. - if (LangStd == LangStandard::lang_opencl) { + if (LangStd == LangStandard::lang_opencl10) { Opts.OpenCL = 1; Opts.AltiVec = 1; Opts.CXXOperatorNames = 1; @@ -784,8 +777,8 @@ IdentifierTable *ClangASTContext::getIdentifierTable() { LangOptions *ClangASTContext::getLanguageOptions() { if (m_language_options_ap.get() == nullptr) { m_language_options_ap.reset(new LangOptions()); - ParseLangArgs(*m_language_options_ap, IK_ObjCXX, GetTargetTriple()); - // InitializeLangOptions(*m_language_options_ap, IK_ObjCXX); + ParseLangArgs(*m_language_options_ap, InputKind::ObjCXX, GetTargetTriple()); + // InitializeLangOptions(*m_language_options_ap, InputKind::ObjCXX); } return m_language_options_ap.get(); } @@ -961,75 +954,60 @@ ClangASTContext::GetBasicTypeEnumeration(const ConstString &name) { static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { // "void" - g_type_map.Append(ConstString("void").GetStringRef(), eBasicTypeVoid); + g_type_map.Append(ConstString("void"), eBasicTypeVoid); // "char" - g_type_map.Append(ConstString("char").GetStringRef(), eBasicTypeChar); - g_type_map.Append(ConstString("signed char").GetStringRef(), - eBasicTypeSignedChar); - g_type_map.Append(ConstString("unsigned char").GetStringRef(), - eBasicTypeUnsignedChar); - g_type_map.Append(ConstString("wchar_t").GetStringRef(), eBasicTypeWChar); - g_type_map.Append(ConstString("signed wchar_t").GetStringRef(), - eBasicTypeSignedWChar); - g_type_map.Append(ConstString("unsigned wchar_t").GetStringRef(), + g_type_map.Append(ConstString("char"), eBasicTypeChar); + g_type_map.Append(ConstString("signed char"), eBasicTypeSignedChar); + g_type_map.Append(ConstString("unsigned char"), eBasicTypeUnsignedChar); + g_type_map.Append(ConstString("wchar_t"), eBasicTypeWChar); + g_type_map.Append(ConstString("signed wchar_t"), eBasicTypeSignedWChar); + g_type_map.Append(ConstString("unsigned wchar_t"), eBasicTypeUnsignedWChar); // "short" - g_type_map.Append(ConstString("short").GetStringRef(), eBasicTypeShort); - g_type_map.Append(ConstString("short int").GetStringRef(), - eBasicTypeShort); - g_type_map.Append(ConstString("unsigned short").GetStringRef(), - eBasicTypeUnsignedShort); - g_type_map.Append(ConstString("unsigned short int").GetStringRef(), + g_type_map.Append(ConstString("short"), eBasicTypeShort); + g_type_map.Append(ConstString("short int"), eBasicTypeShort); + g_type_map.Append(ConstString("unsigned short"), eBasicTypeUnsignedShort); + g_type_map.Append(ConstString("unsigned short int"), eBasicTypeUnsignedShort); // "int" - g_type_map.Append(ConstString("int").GetStringRef(), eBasicTypeInt); - g_type_map.Append(ConstString("signed int").GetStringRef(), - eBasicTypeInt); - g_type_map.Append(ConstString("unsigned int").GetStringRef(), - eBasicTypeUnsignedInt); - g_type_map.Append(ConstString("unsigned").GetStringRef(), - eBasicTypeUnsignedInt); + g_type_map.Append(ConstString("int"), eBasicTypeInt); + g_type_map.Append(ConstString("signed int"), eBasicTypeInt); + g_type_map.Append(ConstString("unsigned int"), eBasicTypeUnsignedInt); + g_type_map.Append(ConstString("unsigned"), eBasicTypeUnsignedInt); // "long" - g_type_map.Append(ConstString("long").GetStringRef(), eBasicTypeLong); - g_type_map.Append(ConstString("long int").GetStringRef(), eBasicTypeLong); - g_type_map.Append(ConstString("unsigned long").GetStringRef(), - eBasicTypeUnsignedLong); - g_type_map.Append(ConstString("unsigned long int").GetStringRef(), + g_type_map.Append(ConstString("long"), eBasicTypeLong); + g_type_map.Append(ConstString("long int"), eBasicTypeLong); + g_type_map.Append(ConstString("unsigned long"), eBasicTypeUnsignedLong); + g_type_map.Append(ConstString("unsigned long int"), eBasicTypeUnsignedLong); // "long long" - g_type_map.Append(ConstString("long long").GetStringRef(), - eBasicTypeLongLong); - g_type_map.Append(ConstString("long long int").GetStringRef(), - eBasicTypeLongLong); - g_type_map.Append(ConstString("unsigned long long").GetStringRef(), + g_type_map.Append(ConstString("long long"), eBasicTypeLongLong); + g_type_map.Append(ConstString("long long int"), eBasicTypeLongLong); + g_type_map.Append(ConstString("unsigned long long"), eBasicTypeUnsignedLongLong); - g_type_map.Append(ConstString("unsigned long long int").GetStringRef(), + g_type_map.Append(ConstString("unsigned long long int"), eBasicTypeUnsignedLongLong); // "int128" - g_type_map.Append(ConstString("__int128_t").GetStringRef(), - eBasicTypeInt128); - g_type_map.Append(ConstString("__uint128_t").GetStringRef(), - eBasicTypeUnsignedInt128); + g_type_map.Append(ConstString("__int128_t"), eBasicTypeInt128); + g_type_map.Append(ConstString("__uint128_t"), eBasicTypeUnsignedInt128); // Miscellaneous - g_type_map.Append(ConstString("bool").GetStringRef(), eBasicTypeBool); - g_type_map.Append(ConstString("float").GetStringRef(), eBasicTypeFloat); - g_type_map.Append(ConstString("double").GetStringRef(), eBasicTypeDouble); - g_type_map.Append(ConstString("long double").GetStringRef(), - eBasicTypeLongDouble); - g_type_map.Append(ConstString("id").GetStringRef(), eBasicTypeObjCID); - g_type_map.Append(ConstString("SEL").GetStringRef(), eBasicTypeObjCSel); - g_type_map.Append(ConstString("nullptr").GetStringRef(), - eBasicTypeNullPtr); + g_type_map.Append(ConstString("bool"), eBasicTypeBool); + g_type_map.Append(ConstString("float"), eBasicTypeFloat); + g_type_map.Append(ConstString("double"), eBasicTypeDouble); + g_type_map.Append(ConstString("long double"), eBasicTypeLongDouble); + g_type_map.Append(ConstString("id"), eBasicTypeObjCID); + g_type_map.Append(ConstString("SEL"), eBasicTypeObjCSel); + g_type_map.Append(ConstString("nullptr"), eBasicTypeNullPtr); g_type_map.Sort(); }); - return g_type_map.Find(name.GetStringRef(), eBasicTypeInvalid); + return g_type_map.Find(name, eBasicTypeInvalid); } return eBasicTypeInvalid; } diff --git a/source/Symbol/GoASTContext.cpp b/source/Symbol/GoASTContext.cpp index 5ca173ae113c..6761a605e46b 100644 --- a/source/Symbol/GoASTContext.cpp +++ b/source/Symbol/GoASTContext.cpp @@ -598,33 +598,32 @@ GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { // "void" - g_type_map.Append(ConstString("void").GetStringRef(), eBasicTypeVoid); + g_type_map.Append(ConstString("void"), eBasicTypeVoid); // "int" - g_type_map.Append(ConstString("int").GetStringRef(), eBasicTypeInt); - g_type_map.Append(ConstString("uint").GetStringRef(), - eBasicTypeUnsignedInt); + g_type_map.Append(ConstString("int"), eBasicTypeInt); + g_type_map.Append(ConstString("uint"), eBasicTypeUnsignedInt); // Miscellaneous - g_type_map.Append(ConstString("bool").GetStringRef(), eBasicTypeBool); + g_type_map.Append(ConstString("bool"), eBasicTypeBool); // Others. Should these map to C types? - g_type_map.Append(ConstString("byte").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("uint8").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("uint16").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("uint32").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("uint64").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("int8").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("int16").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("int32").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("int64").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("float32").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("float64").GetStringRef(), eBasicTypeOther); - g_type_map.Append(ConstString("uintptr").GetStringRef(), eBasicTypeOther); + g_type_map.Append(ConstString("byte"), eBasicTypeOther); + g_type_map.Append(ConstString("uint8"), eBasicTypeOther); + g_type_map.Append(ConstString("uint16"), eBasicTypeOther); + g_type_map.Append(ConstString("uint32"), eBasicTypeOther); + g_type_map.Append(ConstString("uint64"), eBasicTypeOther); + g_type_map.Append(ConstString("int8"), eBasicTypeOther); + g_type_map.Append(ConstString("int16"), eBasicTypeOther); + g_type_map.Append(ConstString("int32"), eBasicTypeOther); + g_type_map.Append(ConstString("int64"), eBasicTypeOther); + g_type_map.Append(ConstString("float32"), eBasicTypeOther); + g_type_map.Append(ConstString("float64"), eBasicTypeOther); + g_type_map.Append(ConstString("uintptr"), eBasicTypeOther); g_type_map.Sort(); }); - return g_type_map.Find(name.GetStringRef(), eBasicTypeInvalid); + return g_type_map.Find(name, eBasicTypeInvalid); } return eBasicTypeInvalid; } diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp index d7898919f45e..eb20b80f4916 100644 --- a/source/Symbol/SymbolFile.cpp +++ b/source/Symbol/SymbolFile.cpp @@ -21,6 +21,10 @@ using namespace lldb_private; +void SymbolFile::PreloadSymbols() { + // No-op for most implementations. +} + SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { std::unique_ptr<SymbolFile> best_symfile_ap; if (obj_file != nullptr) { diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp index 427029802634..1e241df0d90a 100644 --- a/source/Symbol/Symtab.cpp +++ b/source/Symbol/Symtab.cpp @@ -263,36 +263,35 @@ void Symtab::InitNameIndexes() { continue; const Mangled &mangled = symbol->GetMangled(); - entry.cstring = mangled.GetMangledName().GetStringRef(); - if (!entry.cstring.empty()) { + entry.cstring = mangled.GetMangledName(); + if (entry.cstring) { m_name_to_index.Append(entry); if (symbol->ContainsLinkerAnnotations()) { // If the symbol has linker annotations, also add the version without // the annotations. entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations( - entry.cstring)) - .GetStringRef(); + entry.cstring.GetStringRef())); m_name_to_index.Append(entry); } const SymbolType symbol_type = symbol->GetType(); if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver) { - if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' && - (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, - // typeinfo structure, and typeinfo - // name - entry.cstring[2] != 'G' && // avoid guard variables - entry.cstring[2] != 'Z')) // named local entities (if we + llvm::StringRef entry_ref(entry.cstring.GetStringRef()); + if (entry_ref[0] == '_' && entry_ref[1] == 'Z' && + (entry_ref[2] != 'T' && // avoid virtual table, VTT structure, + // typeinfo structure, and typeinfo + // name + entry_ref[2] != 'G' && // avoid guard variables + entry_ref[2] != 'Z')) // named local entities (if we // eventually handle eSymbolTypeData, // we will want this back) { CPlusPlusLanguage::MethodName cxx_method( mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus)); - entry.cstring = - ConstString(cxx_method.GetBasename()).GetStringRef(); - if (!entry.cstring.empty()) { + entry.cstring = ConstString(cxx_method.GetBasename()); + if (entry.cstring) { // ConstString objects permanently store the string in the pool so // calling // GetCString() on the value gets us a const char * that will @@ -300,7 +299,8 @@ void Symtab::InitNameIndexes() { const char *const_context = ConstString(cxx_method.GetContext()).GetCString(); - if (entry.cstring[0] == '~' || + entry_ref = entry.cstring.GetStringRef(); + if (entry_ref[0] == '~' || !cxx_method.GetQualifiers().empty()) { // The first character of the demangled basename is '~' which // means we have a class destructor. We can use this information @@ -341,17 +341,15 @@ void Symtab::InitNameIndexes() { } } - entry.cstring = - mangled.GetDemangledName(symbol->GetLanguage()).GetStringRef(); - if (!entry.cstring.empty()) { + entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()); + if (entry.cstring) { m_name_to_index.Append(entry); if (symbol->ContainsLinkerAnnotations()) { // If the symbol has linker annotations, also add the version without // the annotations. entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations( - entry.cstring)) - .GetStringRef(); + entry.cstring.GetStringRef())); m_name_to_index.Append(entry); } } @@ -359,15 +357,15 @@ void Symtab::InitNameIndexes() { // If the demangled name turns out to be an ObjC name, and // is a category name, add the version without categories to the index // too. - ObjCLanguage::MethodName objc_method(entry.cstring, true); + ObjCLanguage::MethodName objc_method(entry.cstring.GetStringRef(), true); if (objc_method.IsValid(true)) { - entry.cstring = objc_method.GetSelector().GetStringRef(); + entry.cstring = objc_method.GetSelector(); m_selector_to_index.Append(entry); ConstString objc_method_no_category( objc_method.GetFullNameWithoutCategory(true)); if (objc_method_no_category) { - entry.cstring = objc_method_no_category.GetStringRef(); + entry.cstring = objc_method_no_category; m_name_to_index.Append(entry); } } @@ -427,6 +425,11 @@ void Symtab::InitNameIndexes() { } } +void Symtab::PreloadSymbols() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + InitNameIndexes(); +} + void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, bool add_demangled, bool add_mangled, NameToIndexMap &name_to_index_map) const { @@ -444,15 +447,14 @@ void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, const Mangled &mangled = symbol->GetMangled(); if (add_demangled) { - entry.cstring = - mangled.GetDemangledName(symbol->GetLanguage()).GetStringRef(); - if (!entry.cstring.empty()) + entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()); + if (entry.cstring) name_to_index_map.Append(entry); } if (add_mangled) { - entry.cstring = mangled.GetMangledName().GetStringRef(); - if (!entry.cstring.empty()) + entry.cstring = mangled.GetMangledName(); + if (entry.cstring) name_to_index_map.Append(entry); } } @@ -625,7 +627,7 @@ uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, if (!m_name_indexes_computed) InitNameIndexes(); - return m_name_to_index.GetValues(symbol_name.GetStringRef(), indexes); + return m_name_to_index.GetValues(symbol_name, indexes); } return 0; } @@ -644,7 +646,7 @@ uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, std::vector<uint32_t> all_name_indexes; const size_t name_match_count = - m_name_to_index.GetValues(symbol_name.GetStringRef(), all_name_indexes); + m_name_to_index.GetValues(symbol_name, all_name_indexes); for (size_t i = 0; i < name_match_count; ++i) { if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility)) @@ -1068,8 +1070,6 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name, size_t count = 0; std::vector<uint32_t> symbol_indexes; - llvm::StringRef name_cstr = name.GetStringRef(); - // eFunctionNameTypeAuto should be pre-resolved by a call to // Module::LookupInfo::LookupInfo() assert((name_type_mask & eFunctionNameTypeAuto) == 0); @@ -1107,7 +1107,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name, if (!m_basename_to_index.IsEmpty()) { const UniqueCStringMap<uint32_t>::Entry *match; - for (match = m_basename_to_index.FindFirstValueForName(name_cstr); + for (match = m_basename_to_index.FindFirstValueForName(name); match != nullptr; match = m_basename_to_index.FindNextValueForName(match)) { symbol_indexes.push_back(match->value); @@ -1121,7 +1121,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name, if (!m_method_to_index.IsEmpty()) { const UniqueCStringMap<uint32_t>::Entry *match; - for (match = m_method_to_index.FindFirstValueForName(name_cstr); + for (match = m_method_to_index.FindFirstValueForName(name); match != nullptr; match = m_method_to_index.FindNextValueForName(match)) { symbol_indexes.push_back(match->value); @@ -1135,7 +1135,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name, if (!m_selector_to_index.IsEmpty()) { const UniqueCStringMap<uint32_t>::Entry *match; - for (match = m_selector_to_index.FindFirstValueForName(name_cstr); + for (match = m_selector_to_index.FindFirstValueForName(name); match != nullptr; match = m_selector_to_index.FindNextValueForName(match)) { symbol_indexes.push_back(match->value); diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp index df021e3953bc..5c9e92aaaa27 100644 --- a/source/Target/Target.cpp +++ b/source/Target/Target.cpp @@ -1870,6 +1870,11 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec, } } + // Preload symbols outside of any lock, so hopefully we can do this for + // each library in parallel. + if (GetPreloadSymbols()) + module_sp->PreloadSymbols(); + if (old_module_sp && m_images.GetIndexForModule(old_module_sp.get()) != LLDB_INVALID_INDEX32) { @@ -3277,6 +3282,8 @@ static PropertyDefinition g_properties[] = { {"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "debugserver will detach (rather than killing) a process if it " "loses connection with lldb."}, + {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, + "Enable loading of symbol tables before they are needed."}, {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "Disable Address Space Layout Randomization (ASLR)"}, {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, nullptr, @@ -3379,6 +3386,7 @@ enum { ePropertyOutputPath, ePropertyErrorPath, ePropertyDetachOnError, + ePropertyPreloadSymbols, ePropertyDisableASLR, ePropertyDisableSTDIO, ePropertyInlineStrategy, @@ -3641,6 +3649,17 @@ bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) { return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, d); } +bool TargetProperties::GetPreloadSymbols() const { + const uint32_t idx = ePropertyPreloadSymbols; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void TargetProperties::SetPreloadSymbols(bool b) { + const uint32_t idx = ePropertyPreloadSymbols; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + bool TargetProperties::GetDisableASLR() const { const uint32_t idx = ePropertyDisableASLR; return m_collection_sp->GetPropertyAtIndexAsBoolean( diff --git a/source/Utility/ConstString.cpp b/source/Utility/ConstString.cpp index 8adeb6f364ef..49cf8a6d864d 100644 --- a/source/Utility/ConstString.cpp +++ b/source/Utility/ConstString.cpp @@ -38,14 +38,13 @@ public: static StringPoolEntryType & GetStringMapEntryFromKeyData(const char *keyData) { - char *ptr = const_cast<char *>(keyData) - sizeof(StringPoolEntryType); - return *reinterpret_cast<StringPoolEntryType *>(ptr); + return StringPoolEntryType::GetStringMapEntryFromKeyData(keyData); } - size_t GetConstCStringLength(const char *ccstr) const { + static size_t GetConstCStringLength(const char *ccstr) { if (ccstr != nullptr) { - const uint8_t h = hash(llvm::StringRef(ccstr)); - llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); + // Since the entry is read only, and we derive the entry entirely from the + // pointer, we don't need the lock. const StringPoolEntryType &entry = GetStringMapEntryFromKeyData(ccstr); return entry.getKey().size(); } @@ -218,10 +217,8 @@ bool ConstString::operator<(const ConstString &rhs) const { if (m_string == rhs.m_string) return false; - llvm::StringRef lhs_string_ref(m_string, - StringPool().GetConstCStringLength(m_string)); - llvm::StringRef rhs_string_ref( - rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string)); + llvm::StringRef lhs_string_ref(GetStringRef()); + llvm::StringRef rhs_string_ref(rhs.GetStringRef()); // If both have valid C strings, then return the comparison if (lhs_string_ref.data() && rhs_string_ref.data()) @@ -240,7 +237,7 @@ Stream &lldb_private::operator<<(Stream &s, const ConstString &str) { } size_t ConstString::GetLength() const { - return StringPool().GetConstCStringLength(m_string); + return Pool::GetConstCStringLength(m_string); } bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs, @@ -255,10 +252,8 @@ bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs, return false; // perform case insensitive equality test - llvm::StringRef lhs_string_ref( - lhs.m_string, StringPool().GetConstCStringLength(lhs.m_string)); - llvm::StringRef rhs_string_ref( - rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string)); + llvm::StringRef lhs_string_ref(lhs.GetStringRef()); + llvm::StringRef rhs_string_ref(rhs.GetStringRef()); return lhs_string_ref.equals_lower(rhs_string_ref); } @@ -270,10 +265,8 @@ int ConstString::Compare(const ConstString &lhs, const ConstString &rhs, if (lhs_cstr == rhs_cstr) return 0; if (lhs_cstr && rhs_cstr) { - llvm::StringRef lhs_string_ref( - lhs_cstr, StringPool().GetConstCStringLength(lhs_cstr)); - llvm::StringRef rhs_string_ref( - rhs_cstr, StringPool().GetConstCStringLength(rhs_cstr)); + llvm::StringRef lhs_string_ref(lhs.GetStringRef()); + llvm::StringRef rhs_string_ref(rhs.GetStringRef()); if (case_sensitive) { return lhs_string_ref.compare(rhs_string_ref); diff --git a/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/tools/debugserver/debugserver.xcodeproj/project.pbxproj index e0d1b68db702..d97b438ce8e5 100644 --- a/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -101,6 +101,7 @@ AF48558D1D75127500D19C07 /* StdStringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */; }; AFA3FCA11E39984900218D5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49D404611E39260F00570CDC /* Foundation.framework */; }; AFEC3364194A8B0B00FF05C6 /* Genealogy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */; }; + D6631CA91E848FE9006A7B11 /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -219,6 +220,7 @@ AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoTerminal.cpp; sourceTree = "<group>"; }; AF67AC000D34604D0022D128 /* PseudoTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoTerminal.h; sourceTree = "<group>"; }; AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Genealogy.cpp; sourceTree = "<group>"; }; + D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddress.cpp; path = ../../source/Host/common/SocketAddress.cpp; sourceTree = "<group>"; }; ED128B7918E1F163003F6A7B /* libpmenergy.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpmenergy.dylib; path = usr/lib/libpmenergy.dylib; sourceTree = SDKROOT; }; ED128B7A18E1F163003F6A7B /* libpmsample.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpmsample.dylib; path = usr/lib/libpmsample.dylib; sourceTree = SDKROOT; }; EF88788B0D9C7558001831DA /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.applist.plist; sourceTree = "<group>"; }; @@ -251,6 +253,7 @@ 08FB7794FE84155DC02AAC07 /* dbgnub */ = { isa = PBXGroup; children = ( + D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */, 26ACA3330D3E94F200A2120B /* Framework */, 26C637D50C71334A0024798E /* source */, 1AB674ADFE9D54B511CA2CBB /* Products */, @@ -577,6 +580,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D6631CA91E848FE9006A7B11 /* SocketAddress.cpp in Sources */, 26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */, 26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */, 26CE05A9115C36250022F371 /* debugserver.cpp in Sources */, diff --git a/tools/debugserver/source/CMakeLists.txt b/tools/debugserver/source/CMakeLists.txt index 782c946f702f..775a1a127b6f 100644 --- a/tools/debugserver/source/CMakeLists.txt +++ b/tools/debugserver/source/CMakeLists.txt @@ -62,6 +62,7 @@ set(lldbDebugserverCommonSources StdStringExtractor.cpp # JSON reader depends on the following LLDB-common files ${LLDB_SOURCE_DIR}/source/Host/common/StringConvert.cpp + ${LLDB_SOURCE_DIR}/source/Host/common/SocketAddress.cpp # end JSON reader dependencies libdebugserver.cpp PseudoTerminal.cpp diff --git a/tools/debugserver/source/RNBSocket.cpp b/tools/debugserver/source/RNBSocket.cpp index a8d119e455fa..62a3e4f9adf5 100644 --- a/tools/debugserver/source/RNBSocket.cpp +++ b/tools/debugserver/source/RNBSocket.cpp @@ -17,10 +17,15 @@ #include <arpa/inet.h> #include <errno.h> #include <fcntl.h> +#include <map> #include <netdb.h> #include <netinet/in.h> #include <netinet/tcp.h> +#include <sys/event.h> #include <termios.h> +#include <vector> + +#include "lldb/Host/SocketAddress.h" #ifdef WITH_LOCKDOWN #include "lockdown.h" @@ -66,176 +71,161 @@ rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port, // Disconnect without saving errno Disconnect(false); - // Now figure out the hostname that will be attaching and palce it into - struct sockaddr_in listen_addr; - ::memset(&listen_addr, 0, sizeof listen_addr); - listen_addr.sin_len = sizeof listen_addr; - listen_addr.sin_family = AF_INET; - listen_addr.sin_port = htons(port); - listen_addr.sin_addr.s_addr = INADDR_ANY; - - if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) { - DNBLogThreaded("error: failed to resolve connecting host '%s'", - listen_host); + DNBError err; + int queue_id = kqueue(); + if (queue_id < 0) { + err.SetError(errno, DNBError::MachKernel); + err.LogThreaded("error: failed to create kqueue."); return rnb_err; } - DNBError err; - int listen_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (listen_fd == -1) - err.SetError(errno, DNBError::POSIX); + std::map<int, lldb_private::SocketAddress> sockets; + auto addresses = lldb_private::SocketAddress::GetAddressInfo( + listen_host, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol " - "= IPPROTO_TCP ) => socket = %i", - listen_fd); + for (auto address : addresses) { + int sock_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP); + if (sock_fd == -1) + continue; - if (err.Fail()) - return rnb_err; + SetSocketOption(sock_fd, SOL_SOCKET, SO_REUSEADDR, 1); - // enable local address reuse - SetSocketOption(listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); - - struct sockaddr_in sa; - ::memset(&sa, 0, sizeof sa); - sa.sin_len = sizeof sa; - sa.sin_family = AF_INET; - sa.sin_port = htons(port); - sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host - // network interface (this is NOT who can - // connect to us) - int error = ::bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa)); - if (error == -1) - err.SetError(errno, DNBError::POSIX); + address.SetPort(port); - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded( - "::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", - listen_fd); + int error = ::bind(sock_fd, &address.sockaddr(), address.GetLength()); + if (error == -1) { + ClosePort(sock_fd, false); + continue; + } - if (err.Fail()) { - ClosePort(listen_fd, false); - return rnb_err; - } + error = ::listen(sock_fd, 5); + if (error == -1) { + ClosePort(sock_fd, false); + continue; + } - error = ::listen(listen_fd, 5); - if (error == -1) - err.SetError(errno, DNBError::POSIX); + // We were asked to listen on port zero which means we must now read the + // actual port that was given to us as port zero is a special code for "find + // an open port for me". This will only execute on the first socket created, + // subesquent sockets will reuse this port number. + if (port == 0) { + socklen_t sa_len = address.GetLength(); + if (getsockname(sock_fd, &address.sockaddr(), &sa_len) == 0) + port = address.GetPort(); + } - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); + sockets[sock_fd] = address; + } - if (err.Fail()) { - ClosePort(listen_fd, false); + if (sockets.size() == 0) { + err.SetError(errno, DNBError::POSIX); + err.LogThreaded("::listen or ::bind failed"); return rnb_err; } - if (callback) { - // We were asked to listen on port zero which means we - // must now read the actual port that was given to us - // as port zero is a special code for "find an open port - // for me". - if (port == 0) { - socklen_t sa_len = sizeof(sa); - if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) { - port = ntohs(sa.sin_port); - callback(callback_baton, port); - } - } else { - callback(callback_baton, port); - } - } + if (callback) + callback(callback_baton, port); - struct sockaddr_in accept_addr; - ::memset(&accept_addr, 0, sizeof accept_addr); - accept_addr.sin_len = sizeof accept_addr; + std::vector<struct kevent> events; + events.resize(sockets.size()); + int i = 0; + for (auto socket : sockets) { + EV_SET(&events[i++], socket.first, EVFILT_READ, EV_ADD, 0, 0, 0); + } bool accept_connection = false; // Loop until we are happy with our connection while (!accept_connection) { - socklen_t accept_addr_len = sizeof accept_addr; - m_fd = - ::accept(listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); - if (m_fd == -1) - err.SetError(errno, DNBError::POSIX); + struct kevent event_list[4]; + int num_events = + kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded( - "::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, - &accept_addr, accept_addr_len); + if (num_events < 0) { + err.SetError(errno, DNBError::MachKernel); + err.LogThreaded("error: kevent() failed."); + } - if (err.Fail()) - break; + for (int i = 0; i < num_events; ++i) { + auto sock_fd = event_list[i].ident; + auto socket_pair = sockets.find(sock_fd); + if (socket_pair == sockets.end()) + continue; - if (listen_addr.sin_addr.s_addr == INADDR_ANY) - accept_connection = true; - else { - if (accept_addr_len == listen_addr.sin_len && - accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) { + lldb_private::SocketAddress &addr_in = socket_pair->second; + lldb_private::SocketAddress accept_addr; + socklen_t sa_len = accept_addr.GetMaxLength(); + m_fd = ::accept(sock_fd, &accept_addr.sockaddr(), &sa_len); + + if (m_fd == -1) { + err.SetError(errno, DNBError::POSIX); + err.LogThreaded("error: Socket accept failed."); + } + + if (addr_in.IsAnyAddr()) accept_connection = true; - } else { - ::close(m_fd); - m_fd = -1; - const uint8_t *accept_ip = - (const uint8_t *)&accept_addr.sin_addr.s_addr; - const uint8_t *listen_ip = - (const uint8_t *)&listen_addr.sin_addr.s_addr; - ::fprintf(stderr, "error: rejecting incoming connection from " - "%u.%u.%u.%u (expecting %u.%u.%u.%u)\n", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - DNBLogThreaded("error: rejecting connection from %u.%u.%u.%u " - "(expecting %u.%u.%u.%u)", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + else { + if (accept_addr == addr_in) + accept_connection = true; + else { + ::close(m_fd); + m_fd = -1; + ::fprintf( + stderr, + "error: rejecting incoming connection from %s (expecting %s)\n", + accept_addr.GetIPAddress().c_str(), + addr_in.GetIPAddress().c_str()); + DNBLogThreaded("error: rejecting connection from %s (expecting %s)\n", + accept_addr.GetIPAddress().c_str(), + addr_in.GetIPAddress().c_str()); + } } } + if (err.Fail()) + break; + } + for (auto socket : sockets) { + int ListenFd = socket.first; + ClosePort(ListenFd, false); } - ClosePort(listen_fd, false); - - if (err.Fail()) { + if (err.Fail()) return rnb_err; - } else { - // Keep our TCP packets coming without any delays. - SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - } + + // Keep our TCP packets coming without any delays. + SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); return rnb_success; } rnb_err_t RNBSocket::Connect(const char *host, uint16_t port) { + auto result = rnb_err; Disconnect(false); - // Create the socket - m_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (m_fd == -1) - return rnb_err; + auto addresses = lldb_private::SocketAddress::GetAddressInfo( + host, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); - // Enable local address reuse - SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1); + for (auto address : addresses) { + m_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP); + if (m_fd == -1) + continue; - struct sockaddr_in sa; - ::memset(&sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(port); + // Enable local address reuse + SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1); - if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) { - DNBLogThreaded("error: failed to resolve host '%s'", host); - Disconnect(false); - return rnb_err; - } + address.SetPort(port); - if (-1 == ::connect(m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { - Disconnect(false); - return rnb_err; - } + if (-1 == ::connect(m_fd, &address.sockaddr(), address.GetLength())) { + Disconnect(false); + continue; + } + SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - // Keep our TCP packets coming without any delays. - SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - return rnb_success; + result = rnb_success; + break; + } + return result; } rnb_err_t RNBSocket::useFD(int fd) { diff --git a/tools/debugserver/source/debugserver.cpp b/tools/debugserver/source/debugserver.cpp index 0cb72f4ece45..bc1954de334a 100644 --- a/tools/debugserver/source/debugserver.cpp +++ b/tools/debugserver/source/debugserver.cpp @@ -1345,10 +1345,18 @@ int main(int argc, char *argv[]) { show_usage_and_exit(1); } // accept 'localhost:' prefix on port number - - int items_scanned = ::sscanf(argv[0], "%[^:]:%i", str, &port); - if (items_scanned == 2) { - host = str; + std::string host_specifier = argv[0]; + auto colon_location = host_specifier.rfind(':'); + if (colon_location != std::string::npos) { + host = host_specifier.substr(0, colon_location); + std::string port_str = + host_specifier.substr(colon_location + 1, std::string::npos); + char *end_ptr; + port = strtoul(port_str.c_str(), &end_ptr, 0); + if (end_ptr < port_str.c_str() + port_str.size()) + show_usage_and_exit(2); + if (host.front() == '[' && host.back() == ']') + host = host.substr(1, host.size() - 2); DNBLogDebug("host = '%s' port = %i", host.c_str(), port); } else { // No hostname means "localhost" diff --git a/tools/lldb-server/Acceptor.cpp b/tools/lldb-server/Acceptor.cpp index e6e73f8bdb6b..48a364886dc3 100644 --- a/tools/lldb-server/Acceptor.cpp +++ b/tools/lldb-server/Acceptor.cpp @@ -62,8 +62,7 @@ Error Acceptor::Listen(int backlog) { Error Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) { Socket *conn_socket = nullptr; - auto error = m_listener_socket_up->Accept( - StringRef(m_name), child_processes_inherit, conn_socket); + auto error = m_listener_socket_up->Accept(conn_socket); if (error.Success()) conn = new ConnectionFileDescriptor(conn_socket); diff --git a/unittests/Host/SocketTest.cpp b/unittests/Host/SocketTest.cpp index 7abb010a9089..eda3a11fc109 100644 --- a/unittests/Host/SocketTest.cpp +++ b/unittests/Host/SocketTest.cpp @@ -44,8 +44,7 @@ protected: const char *listen_remote_address, bool child_processes_inherit, Socket **accept_socket, Error *error) { - *error = listen_socket->Accept(listen_remote_address, - child_processes_inherit, *accept_socket); + *error = listen_socket->Accept(*accept_socket); } template <typename SocketType> @@ -56,7 +55,7 @@ protected: bool child_processes_inherit = false; Error error; std::unique_ptr<SocketType> listen_socket_up( - new SocketType(child_processes_inherit, error)); + new SocketType(true, child_processes_inherit)); EXPECT_FALSE(error.Fail()); error = listen_socket_up->Listen(listen_remote_address, 5); EXPECT_FALSE(error.Fail()); @@ -70,7 +69,7 @@ protected: std::string connect_remote_address = get_connect_addr(*listen_socket_up); std::unique_ptr<SocketType> connect_socket_up( - new SocketType(child_processes_inherit, error)); + new SocketType(true, child_processes_inherit)); EXPECT_FALSE(error.Fail()); error = connect_socket_up->Connect(connect_remote_address); EXPECT_FALSE(error.Fail()); @@ -141,6 +140,20 @@ TEST_F(SocketTest, DecodeHostAndPort) { EXPECT_STREQ("65535", port_str.c_str()); EXPECT_EQ(65535, port); EXPECT_TRUE(error.Success()); + + EXPECT_TRUE( + Socket::DecodeHostAndPort("[::1]:12345", host_str, port_str, port, &error)); + EXPECT_STREQ("::1", host_str.c_str()); + EXPECT_STREQ("12345", port_str.c_str()); + EXPECT_EQ(12345, port); + EXPECT_TRUE(error.Success()); + + EXPECT_TRUE( + Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345", host_str, port_str, port, &error)); + EXPECT_STREQ("abcd:12fg:AF58::1", host_str.c_str()); + EXPECT_STREQ("12345", port_str.c_str()); + EXPECT_EQ(12345, port); + EXPECT_TRUE(error.Success()); } #ifndef LLDB_DISABLE_POSIX diff --git a/unittests/ObjectFile/ELF/CMakeLists.txt b/unittests/ObjectFile/ELF/CMakeLists.txt index 4cae7ab2c0d6..a182f4a4244e 100644 --- a/unittests/ObjectFile/ELF/CMakeLists.txt +++ b/unittests/ObjectFile/ELF/CMakeLists.txt @@ -1,7 +1,17 @@ add_lldb_unittest(ObjectFileELFTests TestELFHeader.cpp + TestObjectFileELF.cpp LINK_LIBS lldbPluginObjectFileELF + lldbPluginSymbolVendorELF lldbCore ) + +add_dependencies(ObjectFileELFTests yaml2obj) +add_definitions(-DYAML2OBJ="$<TARGET_FILE:yaml2obj>") + +set(test_inputs + sections-resolve-consistently.yaml + ) +add_unittest_inputs(ObjectFileELFTests "${test_inputs}") diff --git a/unittests/ObjectFile/ELF/Inputs/sections-resolve-consistently.yaml b/unittests/ObjectFile/ELF/Inputs/sections-resolve-consistently.yaml new file mode 100644 index 000000000000..98b68bd2773c --- /dev/null +++ b/unittests/ObjectFile/ELF/Inputs/sections-resolve-consistently.yaml @@ -0,0 +1,50 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x0000000000400180 +Sections: + - Name: .note.gnu.build-id + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x0000000000400158 + AddressAlign: 0x0000000000000004 + Content: 040000001400000003000000474E55003F3EC29E3FD83E49D18C4D49CD8A730CC13117B6 + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x0000000000400180 + AddressAlign: 0x0000000000000010 + Content: 554889E58B042500106000890425041060005DC3 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x0000000000601000 + AddressAlign: 0x0000000000000004 + Content: 2F000000 + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x0000000000601004 + AddressAlign: 0x0000000000000004 + Size: 0x0000000000000004 +Symbols: + Global: + - Name: Y + Type: STT_OBJECT + Section: .data + Value: 0x0000000000601000 + Size: 0x0000000000000004 + - Name: _start + Type: STT_FUNC + Section: .text + Value: 0x0000000000400180 + Size: 0x0000000000000014 + - Name: X + Type: STT_OBJECT + Section: .bss + Value: 0x0000000000601004 + Size: 0x0000000000000004 +... diff --git a/unittests/ObjectFile/ELF/TestObjectFileELF.cpp b/unittests/ObjectFile/ELF/TestObjectFileELF.cpp new file mode 100644 index 000000000000..6ed9b2357bb1 --- /dev/null +++ b/unittests/ObjectFile/ELF/TestObjectFileELF.cpp @@ -0,0 +1,105 @@ +//===-- TestObjectFileELF.cpp -----------------------------------*- C++ -*-===// +// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/HostInfo.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" + +#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h" + +extern const char *TestMainArgv0; + +using namespace lldb_private; +using namespace lldb; + +class ObjectFileELFTest : public testing::Test { +public: + void SetUp() override { + HostInfo::Initialize(); + ObjectFileELF::Initialize(); + SymbolVendorELF::Initialize(); + + m_inputs_folder = llvm::sys::path::parent_path(TestMainArgv0); + llvm::sys::path::append(m_inputs_folder, "Inputs"); + llvm::sys::fs::make_absolute(m_inputs_folder); + } + + void TearDown() override { + SymbolVendorELF::Terminate(); + ObjectFileELF::Terminate(); + HostInfo::Terminate(); + } + +protected: + llvm::SmallString<128> m_inputs_folder; +}; + +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + llvm::SmallString<128> MessageStorage; \ + llvm::raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } + +TEST_F(ObjectFileELFTest, SectionsResolveConsistently) { + llvm::SmallString<128> yaml = m_inputs_folder; + llvm::sys::path::append(yaml, "sections-resolve-consistently.yaml"); + llvm::SmallString<128> obj = m_inputs_folder; + ASSERT_NO_ERROR(llvm::sys::fs::createTemporaryFile( + "sections-resolve-consistently-%%%%%%", "obj", obj)); + + llvm::FileRemover remover(obj); + const char *args[] = {YAML2OBJ, yaml.c_str(), nullptr}; + llvm::StringRef obj_ref = obj; + const llvm::StringRef *redirects[] = {nullptr, &obj_ref, nullptr}; + ASSERT_EQ(0, llvm::sys::ExecuteAndWait(YAML2OBJ, args, nullptr, redirects)); + uint64_t size; + ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size)); + ASSERT_GT(size, 0u); + + ModuleSpec spec{FileSpec(obj, false)}; + spec.GetSymbolFileSpec().SetFile(obj, false); + auto module_sp = std::make_shared<Module>(spec); + SectionList *list = module_sp->GetSectionList(); + ASSERT_NE(nullptr, list); + + auto bss_sp = list->FindSectionByName(ConstString(".bss")); + ASSERT_NE(nullptr, bss_sp); + auto data_sp = list->FindSectionByName(ConstString(".data")); + ASSERT_NE(nullptr, data_sp); + auto text_sp = list->FindSectionByName(ConstString(".text")); + ASSERT_NE(nullptr, text_sp); + + const Symbol *X = module_sp->FindFirstSymbolWithNameAndType(ConstString("X"), + eSymbolTypeAny); + ASSERT_NE(nullptr, X); + EXPECT_EQ(bss_sp, X->GetAddress().GetSection()); + + const Symbol *Y = module_sp->FindFirstSymbolWithNameAndType(ConstString("Y"), + eSymbolTypeAny); + ASSERT_NE(nullptr, Y); + EXPECT_EQ(data_sp, Y->GetAddress().GetSection()); + + const Symbol *start = module_sp->FindFirstSymbolWithNameAndType( + ConstString("_start"), eSymbolTypeAny); + ASSERT_NE(nullptr, start); + EXPECT_EQ(text_sp, start->GetAddress().GetSection()); +} diff --git a/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp b/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp index 08501f50f65a..6440e814efd4 100644 --- a/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp +++ b/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp @@ -33,15 +33,14 @@ void GDBRemoteTest::TearDownTestCase() { void Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server) { bool child_processes_inherit = false; Error error; - TCPSocket listen_socket(child_processes_inherit, error); + TCPSocket listen_socket(true, child_processes_inherit); ASSERT_FALSE(error.Fail()); error = listen_socket.Listen("127.0.0.1:0", 5); ASSERT_FALSE(error.Fail()); Socket *accept_socket; std::future<Error> accept_error = std::async(std::launch::async, [&] { - return listen_socket.Accept("127.0.0.1:0", child_processes_inherit, - accept_socket); + return listen_socket.Accept(accept_socket); }); char connect_remote_address[64]; diff --git a/unittests/debugserver/RNBSocketTest.cpp b/unittests/debugserver/RNBSocketTest.cpp index 997041f6154b..76a1b49064f5 100644 --- a/unittests/debugserver/RNBSocketTest.cpp +++ b/unittests/debugserver/RNBSocketTest.cpp @@ -53,9 +53,21 @@ static void ServerCallbackv4(const void *baton, in_port_t port) { } void TestSocketListen(const char *addr) { + // Skip IPv6 tests if there isn't a valid interafce + auto addresses = lldb_private::SocketAddress::GetAddressInfo( + addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + if (addresses.size() == 0) + return; + + char addr_wrap[256]; + if (addresses.front().GetFamily() == AF_INET6) + sprintf(addr_wrap, "[%s]", addr); + else + sprintf(addr_wrap, "%s", addr); + RNBSocket server_socket; auto result = - server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr); + server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr_wrap); ASSERT_TRUE(result == rnb_success); result = server_socket.Write(hello.c_str(), hello.length()); ASSERT_TRUE(result == rnb_success); @@ -71,9 +83,20 @@ void TestSocketListen(const char *addr) { TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); } +TEST(RNBSocket, LoopBackListenIPv6) { TestSocketListen("::1"); } + void TestSocketConnect(const char *addr) { + // Skip IPv6 tests if there isn't a valid interafce + auto addresses = lldb_private::SocketAddress::GetAddressInfo( + addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + if (addresses.size() == 0) + return; + char addr_wrap[256]; - sprintf(addr_wrap, "%s:0", addr); + if (addresses.front().GetFamily() == AF_INET6) + sprintf(addr_wrap, "[%s]:0", addr); + else + sprintf(addr_wrap, "%s:0", addr); Socket *server_socket; Predicate<uint16_t> port_predicate; @@ -96,7 +119,7 @@ void TestSocketConnect(const char *addr) { ASSERT_EQ(bye, goodbye); } else { Socket *connected_socket; - err = server_socket->Accept(addr_wrap, false, connected_socket); + err = server_socket->Accept(connected_socket); if (err.Fail()) { llvm::errs() << err.AsCString(); abort(); @@ -131,3 +154,5 @@ void TestSocketConnect(const char *addr) { } TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); } + +TEST(RNBSocket, LoopBackConnectIPv6) { TestSocketConnect("::1"); } |