diff options
15 files changed, 844 insertions, 29 deletions
diff --git a/lldb/include/lldb/Core/ConnectionMachPort.h b/lldb/include/lldb/Core/ConnectionMachPort.h new file mode 100644 index 00000000000..80adac79ba8 --- /dev/null +++ b/lldb/include/lldb/Core/ConnectionMachPort.h @@ -0,0 +1,91 @@ +//===-- ConnectionMachPort.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#if defined(__APPLE__) + +#ifndef liblldb_ConnectionMachPort_h_ +#define liblldb_ConnectionMachPort_h_ + +// C Includes +#include <mach/mach.h> + +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Connection.h" + +class ConnectionMachPort : + public lldb_private::Connection +{ +public: + ConnectionMachPort (); + + virtual + ~ConnectionMachPort (); + + virtual bool + IsConnected () const; + + virtual lldb::ConnectionStatus + BytesAvailable (uint32_t timeout_usec, lldb_private::Error *error_ptr); + + virtual lldb::ConnectionStatus + Connect (const char *s, lldb_private::Error *error_ptr); + + virtual lldb::ConnectionStatus + Disconnect (lldb_private::Error *error_ptr); + + virtual size_t + Read (void *dst, + size_t dst_len, + lldb::ConnectionStatus &status, + lldb_private::Error *error_ptr); + + virtual size_t + Write (const void *src, + size_t src_len, + lldb::ConnectionStatus &status, + lldb_private::Error *error_ptr); + + lldb::ConnectionStatus + BootstrapCheckIn (const char *port_name, + lldb_private::Error *error_ptr); + + lldb::ConnectionStatus + BootstrapLookup (const char *port_name, + lldb_private::Error *error_ptr); + + struct PayloadType + { + uint32_t command; + uint32_t data_length; + uint8_t data[32]; + }; + + kern_return_t + Send (const PayloadType &payload); + + kern_return_t + Receive (PayloadType &payload); + + +protected: + mach_port_t m_task; + mach_port_t m_port; + +private: + + + DISALLOW_COPY_AND_ASSIGN (ConnectionMachPort); +}; + +#endif // liblldb_ConnectionMachPort_h_ + +#endif // #if defined(__APPLE__)
\ No newline at end of file diff --git a/lldb/include/lldb/Core/ConnectionSharedMemory.h b/lldb/include/lldb/Core/ConnectionSharedMemory.h new file mode 100644 index 00000000000..65b41b1fa21 --- /dev/null +++ b/lldb/include/lldb/Core/ConnectionSharedMemory.h @@ -0,0 +1,66 @@ +//===-- ConnectionSharedMemory.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ConnectionSharedMemory_h_ +#define liblldb_ConnectionSharedMemory_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Connection.h" +#include "lldb/Core/DataBufferMemoryMap.h" + +namespace lldb_private { + +class ConnectionSharedMemory : + public Connection +{ +public: + + ConnectionSharedMemory (); + + virtual + ~ConnectionSharedMemory (); + + virtual bool + IsConnected () const; + + virtual lldb::ConnectionStatus + BytesAvailable (uint32_t timeout_usec, Error *error_ptr); + + virtual lldb::ConnectionStatus + Connect (const char *s, Error *error_ptr); + + virtual lldb::ConnectionStatus + Disconnect (Error *error_ptr); + + virtual size_t + Read (void *dst, size_t dst_len, lldb::ConnectionStatus &status, Error *error_ptr); + + virtual size_t + Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + + lldb::ConnectionStatus + Open (bool create, const char *name, size_t size, Error *error_ptr); + +protected: + + std::string m_name; + int m_fd; // One buffer that contains all we need + DataBufferMemoryMap m_mmap; +private: + DISALLOW_COPY_AND_ASSIGN (ConnectionSharedMemory); +}; + +} // namespace lldb_private + +#endif // liblldb_ConnectionSharedMemory_h_ diff --git a/lldb/include/lldb/Core/DataBufferMemoryMap.h b/lldb/include/lldb/Core/DataBufferMemoryMap.h index f6bd2e69d61..d3a5e954cc2 100644 --- a/lldb/include/lldb/Core/DataBufferMemoryMap.h +++ b/lldb/include/lldb/Core/DataBufferMemoryMap.h @@ -108,7 +108,8 @@ public: size_t MemoryMapFromFileSpec (const FileSpec* file, off_t offset = 0, - size_t length = SIZE_MAX); + size_t length = SIZE_MAX, + bool writeable = false); //------------------------------------------------------------------ /// Memory map all or part of a file. @@ -134,7 +135,11 @@ public: /// The number of bytes mapped starting from the \a offset. //------------------------------------------------------------------ size_t - MemoryMapFromFileDescriptor (int fd, off_t offset = 0, size_t length = SIZE_MAX); + MemoryMapFromFileDescriptor (int fd, + off_t offset, + size_t length, + bool write, + bool fd_is_file); protected: //------------------------------------------------------------------ @@ -144,7 +149,6 @@ protected: size_t m_mmap_size; ///< The actual number of bytes that were mapped when \c mmap() was called uint8_t *m_data; ///< The data the user requested somewhere within the memory mapped data. size_t m_size; ///< The size of the data the user got when data was requested - Error m_error; ///< An error object that describes any errors that occurred during the memory mapping process private: DISALLOW_COPY_AND_ASSIGN (DataBufferMemoryMap); diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 031a15f4f3e..3ba9b77a935 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -18,6 +18,8 @@ 265ABF6310F42EE900531910 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; }; 26651A16133BF9CD005B64B7 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 26651A15133BF9CC005B64B7 /* Opcode.h */; }; 26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26651A17133BF9DF005B64B7 /* Opcode.cpp */; }; + 266603CA1345B5A8004DA8B6 /* ConnectionSharedMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266603C91345B5A8004DA8B6 /* ConnectionSharedMemory.cpp */; }; + 266603CD1345B5C0004DA8B6 /* ConnectionSharedMemory.h in Headers */ = {isa = PBXBuildFile; fileRef = 266603CC1345B5C0004DA8B6 /* ConnectionSharedMemory.h */; }; 2668020E115FD12C008E1FE4 /* lldb-defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668020F115FD12C008E1FE4 /* lldb-enumerations.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680214115FD12C008E1FE4 /* lldb-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2910F1B3BC00F91463 /* lldb-types.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -60,6 +62,8 @@ 26680336116005EF008E1FE4 /* SBBreakpointLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */; }; 26680337116005F1008E1FE4 /* SBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */; }; 2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; }; + 2671A0CE134825F6003A87BB /* ConnectionMachPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */; }; + 2671A0D013482601003A87BB /* ConnectionMachPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */; }; 26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; }; 26744EF21338317700EF765A /* GDBRemoteCommunicationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */; }; 26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; }; @@ -635,6 +639,8 @@ 26651A14133BEC76005B64B7 /* lldb-public.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-public.h"; path = "include/lldb/lldb-public.h"; sourceTree = "<group>"; }; 26651A15133BF9CC005B64B7 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Opcode.h; path = include/lldb/Core/Opcode.h; sourceTree = "<group>"; }; 26651A17133BF9DF005B64B7 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Opcode.cpp; path = source/Core/Opcode.cpp; sourceTree = "<group>"; }; + 266603C91345B5A8004DA8B6 /* ConnectionSharedMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionSharedMemory.cpp; path = source/Core/ConnectionSharedMemory.cpp; sourceTree = "<group>"; }; + 266603CC1345B5C0004DA8B6 /* ConnectionSharedMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionSharedMemory.h; path = include/lldb/Core/ConnectionSharedMemory.h; sourceTree = "<group>"; }; 26680207115FD0ED008E1FE4 /* LLDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LLDB.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 266960591199F4230075C61A /* build-llvm.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = "build-llvm.pl"; sourceTree = "<group>"; }; 2669605A1199F4230075C61A /* build-swig-wrapper-classes.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "build-swig-wrapper-classes.sh"; sourceTree = "<group>"; }; @@ -649,6 +655,8 @@ 266A42D5128E3FFB0090CF7C /* ClangNamespaceDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangNamespaceDecl.cpp; path = source/Symbol/ClangNamespaceDecl.cpp; sourceTree = "<group>"; }; 266A42D7128E40040090CF7C /* ClangNamespaceDecl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangNamespaceDecl.h; path = include/lldb/Symbol/ClangNamespaceDecl.h; sourceTree = "<group>"; }; 266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = "<group>"; }; + 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = "<group>"; }; + 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = "<group>"; }; 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = "<group>"; }; 2672D8471189055500FF4019 /* CommandObjectFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectFrame.h; path = source/Commands/CommandObjectFrame.h; sourceTree = "<group>"; }; 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClient.cpp; sourceTree = "<group>"; }; @@ -1796,6 +1804,10 @@ 26BC7E6F10F1B85900F91463 /* Connection.cpp */, 26BC7D5810F1B77400F91463 /* ConnectionFileDescriptor.h */, 26BC7E7010F1B85900F91463 /* ConnectionFileDescriptor.cpp */, + 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */, + 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */, + 266603CC1345B5C0004DA8B6 /* ConnectionSharedMemory.h */, + 266603C91345B5A8004DA8B6 /* ConnectionSharedMemory.cpp */, 26BC7D7C10F1B77400F91463 /* ConstString.h */, 26BC7E9410F1B85900F91463 /* ConstString.cpp */, 26BC7D5910F1B77400F91463 /* DataBuffer.h */, @@ -2528,6 +2540,8 @@ 264A97C0133918BC0017F0BE /* PlatformRemoteGDBServer.h in Headers */, 2697A54E133A6305004E4240 /* PlatformDarwin.h in Headers */, 26651A16133BF9CD005B64B7 /* Opcode.h in Headers */, + 266603CD1345B5C0004DA8B6 /* ConnectionSharedMemory.h in Headers */, + 2671A0CE134825F6003A87BB /* ConnectionMachPort.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3088,6 +3102,8 @@ 264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */, 2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */, 26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */, + 266603CA1345B5A8004DA8B6 /* ConnectionSharedMemory.cpp in Sources */, + 2671A0D013482601003A87BB /* ConnectionMachPort.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/Core/ConnectionMachPort.cpp b/lldb/source/Core/ConnectionMachPort.cpp new file mode 100644 index 00000000000..cb0344b6032 --- /dev/null +++ b/lldb/source/Core/ConnectionMachPort.cpp @@ -0,0 +1,319 @@ +//===-- ConnectionMachPort.cpp ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#if defined(__APPLE__) + +#include "lldb/Core/ConnectionMachPort.h" + +// C Includes +#include <servers/bootstrap.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private-log.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/Log.h" + +using namespace lldb; +using namespace lldb_private; + +struct MessageType +{ + mach_msg_header_t head; + ConnectionMachPort::PayloadType payload; +}; + + + +ConnectionMachPort::ConnectionMachPort () : + Connection(), + m_task(mach_task_self()), + m_port(MACH_PORT_TYPE_NONE) +{ +} + +ConnectionMachPort::~ConnectionMachPort () +{ + Disconnect (NULL); +} + +bool +ConnectionMachPort::IsConnected () const +{ + return m_port != MACH_PORT_TYPE_NONE; +} + +ConnectionStatus +ConnectionMachPort::Connect (const char *s, Error *error_ptr) +{ + if (IsConnected()) + { + if (error_ptr) + error_ptr->SetErrorString ("already connected"); + return eConnectionStatusError; + } + + if (s == NULL || s[0] == '\0') + { + if (error_ptr) + error_ptr->SetErrorString ("empty connect URL"); + return eConnectionStatusError; + } + + ConnectionStatus status = eConnectionStatusError; + + if (strncmp (s, "bootstrap-checkin://", strlen("bootstrap-checkin://"))) + { + s += strlen("bootstrap-checkin://"); + + if (*s) + { + status = BootstrapCheckIn (s, error_ptr); + } + else + { + if (error_ptr) + error_ptr->SetErrorString ("bootstrap port name is empty"); + } + } + else if (strncmp (s, "bootstrap-lookup://", strlen("bootstrap-lookup://"))) + { + s += strlen("bootstrap-lookup://"); + if (*s) + { + status = BootstrapLookup (s, error_ptr); + } + else + { + if (error_ptr) + error_ptr->SetErrorString ("bootstrap port name is empty"); + } + } + else + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s); + } + + + if (status == eConnectionStatusSuccess) + { + if (error_ptr) + error_ptr->Clear(); + } + else + { + Disconnect(NULL); + } + + return status; +} + +ConnectionStatus +ConnectionMachPort::BootstrapCheckIn (const char *port, Error *error_ptr) +{ + mach_port_t bootstrap_port = MACH_PORT_TYPE_NONE; + + /* Getting bootstrap server port */ + kern_return_t kret = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); + if (kret == KERN_SUCCESS) + { + name_t port_name; + int len = snprintf(port_name, sizeof(port_name), "%s", port); + if (len < sizeof(port_name)) + { + kret = ::bootstrap_check_in (bootstrap_port, + port_name, + &m_port); + } + else + { + Disconnect(NULL); + if (error_ptr) + error_ptr->SetErrorString ("bootstrap is too long"); + return eConnectionStatusError; + } + } + + if (kret != KERN_SUCCESS) + { + Disconnect(NULL); + if (error_ptr) + error_ptr->SetError (kret, eErrorTypeMachKernel); + return eConnectionStatusError; + } + return eConnectionStatusSuccess; +} + +lldb::ConnectionStatus +ConnectionMachPort::BootstrapLookup (const char *port, + Error *error_ptr) +{ + name_t port_name; + + if (port && port[0]) + { + if (::snprintf (port_name, sizeof (port_name), "%s", port) >= sizeof (port_name)) + { + if (error_ptr) + error_ptr->SetErrorString ("port netname is too long"); + return eConnectionStatusError; + } + } + else + { + if (error_ptr) + error_ptr->SetErrorString ("empty port netname"); + return eConnectionStatusError; + } + + mach_port_t bootstrap_port = MACH_PORT_TYPE_NONE; + + /* Getting bootstrap server port */ + kern_return_t kret = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); + if (kret == KERN_SUCCESS) + { + kret = ::bootstrap_look_up (bootstrap_port, + port_name, + &m_port); + } + + if (kret != KERN_SUCCESS) + { + if (error_ptr) + error_ptr->SetError (kret, eErrorTypeMachKernel); + return eConnectionStatusError; + } + + return eConnectionStatusSuccess; +} + +ConnectionStatus +ConnectionMachPort::Disconnect (Error *error_ptr) +{ + kern_return_t kret; + + // TODO: verify if we need to netname_check_out for + // either or both + if (m_port != MACH_PORT_TYPE_NONE) + { + kret = ::mach_port_deallocate (m_task, m_port); + if (error_ptr) + error_ptr->SetError (kret, eErrorTypeMachKernel); + m_port = MACH_PORT_TYPE_NONE; + } + + return eConnectionStatusSuccess; +} + +size_t +ConnectionMachPort::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr) +{ + PayloadType payload; + + kern_return_t kret = Receive (payload); + if (kret == KERN_SUCCESS) + { + memcpy (dst, payload.data, payload.data_length); + status = eConnectionStatusSuccess; + return payload.data_length; + } + + if (error_ptr) + error_ptr->SetError (kret, eErrorTypeMachKernel); + status = eConnectionStatusError; + return 0; +} + +size_t +ConnectionMachPort::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) +{ + PayloadType payload; + payload.command = 0; + payload.data_length = src_len; + const size_t max_payload_size = sizeof(payload.data); + if (src_len > max_payload_size) + payload.data_length = max_payload_size; + memcpy (payload.data, src, payload.data_length); + + if (Send (payload) == KERN_SUCCESS) + { + status = eConnectionStatusSuccess; + return payload.data_length; + } + status = eConnectionStatusError; + return 0; +} + +ConnectionStatus +ConnectionMachPort::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) +{ + return eConnectionStatusLostConnection; +} + +kern_return_t +ConnectionMachPort::Send (const PayloadType &payload) +{ + struct MessageType message; + + /* (i) Form the message : */ + + /* (i.a) Fill the header fields : */ + message.head.msgh_bits = MACH_MSGH_BITS_REMOTE (MACH_MSG_TYPE_MAKE_SEND) | + MACH_MSGH_BITS_OTHER (MACH_MSGH_BITS_COMPLEX); + message.head.msgh_size = sizeof(MessageType); + message.head.msgh_local_port = MACH_PORT_NULL; + message.head.msgh_remote_port = m_port; + + /* (i.b) Explain the message type ( an integer ) */ + // message.type.msgt_name = MACH_MSG_TYPE_INTEGER_32; + // message.type.msgt_size = 32; + // message.type.msgt_number = 1; + // message.type.msgt_inline = TRUE; + // message.type.msgt_longform = FALSE; + // message.type.msgt_deallocate = FALSE; + /* message.type.msgt_unused = 0; */ /* not needed, I think */ + + /* (i.c) Fill the message with the given integer : */ + message.payload = payload; + + /* (ii) Send the message : */ + kern_return_t kret = ::mach_msg (&message.head, + MACH_SEND_MSG, + message.head.msgh_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + + return kret; +} + +kern_return_t +ConnectionMachPort::Receive (PayloadType &payload) +{ + MessageType message; + message.head.msgh_size = sizeof(MessageType); + + kern_return_t kret = ::mach_msg (&message.head, + MACH_RCV_MSG, + 0, + sizeof(MessageType), + m_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + + if (kret == KERN_SUCCESS) + payload = message.payload; + + return kret; +} + + +#endif // #if defined(__APPLE__) diff --git a/lldb/source/Core/ConnectionSharedMemory.cpp b/lldb/source/Core/ConnectionSharedMemory.cpp new file mode 100644 index 00000000000..943e0c339a7 --- /dev/null +++ b/lldb/source/Core/ConnectionSharedMemory.cpp @@ -0,0 +1,127 @@ +//===-- ConnectionSharedMemory.cpp ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ConnectionSharedMemory.h" + +// C Includes +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> +#include <sys/file.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private-log.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/Log.h" + +using namespace lldb; +using namespace lldb_private; + +ConnectionSharedMemory::ConnectionSharedMemory () : + Connection(), + m_name(), + m_fd (-1), + m_mmap() +{ +} + +ConnectionSharedMemory::~ConnectionSharedMemory () +{ + Disconnect (NULL); +} + +bool +ConnectionSharedMemory::IsConnected () const +{ + return m_fd >= 0; +} + +ConnectionStatus +ConnectionSharedMemory::Connect (const char *s, Error *error_ptr) +{ +// if (s && s[0]) +// { +// if (strstr(s, "shm-create://")) +// { +// } +// else if (strstr(s, "shm-connect://")) +// { +// } +// if (error_ptr) +// error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s); +// return eConnectionStatusError; +// } + if (error_ptr) + error_ptr->SetErrorString("invalid connect arguments"); + return eConnectionStatusError; +} + +ConnectionStatus +ConnectionSharedMemory::Disconnect (Error *error_ptr) +{ + m_mmap.Clear(); + if (!m_name.empty()) + { + shm_unlink (m_name.c_str()); + m_name.clear(); + } + return eConnectionStatusSuccess; +} + +size_t +ConnectionSharedMemory::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr) +{ + status = eConnectionStatusSuccess; + return 0; +} + +size_t +ConnectionSharedMemory::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) +{ + status = eConnectionStatusSuccess; + return 0; +} + +ConnectionStatus +ConnectionSharedMemory::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) +{ + return eConnectionStatusLostConnection; +} + +ConnectionStatus +ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error *error_ptr) +{ + if (m_fd != -1) + { + if (error_ptr) + error_ptr->SetErrorString("already open"); + return eConnectionStatusError; + } + + m_name.assign (name); + int oflag = O_RDWR; + if (create) + oflag |= O_CREAT; + m_fd = ::shm_open (m_name.c_str(), oflag, S_IRUSR|S_IWUSR); + + if (create) + ::ftruncate (m_fd, size); + + if (m_mmap.MemoryMapFromFileDescriptor(m_fd, 0, size, true, false) == size) + return eConnectionStatusSuccess; + + Disconnect(NULL); + return eConnectionStatusError; +} + diff --git a/lldb/source/Core/DataBufferMemoryMap.cpp b/lldb/source/Core/DataBufferMemoryMap.cpp index f1c0f237f2f..83060d5584e 100644 --- a/lldb/source/Core/DataBufferMemoryMap.cpp +++ b/lldb/source/Core/DataBufferMemoryMap.cpp @@ -27,8 +27,7 @@ DataBufferMemoryMap::DataBufferMemoryMap() : m_mmap_addr(NULL), m_mmap_size(0), m_data(NULL), - m_size(0), - m_error() + m_size(0) { } @@ -85,14 +84,6 @@ DataBufferMemoryMap::Clear() m_data = NULL; m_size = 0; } - m_error.Clear(); -} - - -const Error & -DataBufferMemoryMap::GetError() const -{ - return m_error; } //---------------------------------------------------------------------- @@ -104,23 +95,33 @@ DataBufferMemoryMap::GetError() const // offset. //---------------------------------------------------------------------- size_t -DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* file, off_t offset, size_t length) +DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* file, + off_t offset, + size_t length, + bool writeable) { if (file != NULL) { char path[PATH_MAX]; if (file->GetPath(path, sizeof(path))) { - int fd = ::open(path, O_RDONLY, 0); + int oflag = 0; + if (writeable) + oflag = O_RDWR; + else + oflag = O_RDONLY; + + int fd = ::open(path, oflag, 0); if (fd >= 0) { - MemoryMapFromFileDescriptor (fd, offset, length); + const bool fd_is_file = true; + MemoryMapFromFileDescriptor (fd, offset, length, writeable, fd_is_file); ::close(fd); return GetByteSize(); } else { - m_error.SetErrorToErrno(); + //error.SetErrorToErrno(); return 0; } } @@ -144,7 +145,11 @@ DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* file, off_t offset, // Number of bytes mapped starting from the requested offset. //---------------------------------------------------------------------- size_t -DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, off_t offset, size_t length) +DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, + off_t offset, + size_t length, + bool writeable, + bool fd_is_file) { Clear(); if (fd >= 0) @@ -167,18 +172,27 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, off_t offset, size_t l if (length > 0) { - m_mmap_addr = (uint8_t *)::mmap(NULL, length, PROT_READ, MAP_FILE | MAP_SHARED, fd, offset); + int prot = PROT_READ; + if (writeable) + prot |= PROT_WRITE; + + int flags = MAP_SHARED; + if (fd_is_file) + flags |= MAP_FILE; + + m_mmap_addr = (uint8_t *)::mmap(NULL, length, prot, flags, fd, offset); if (m_mmap_addr == (void*)-1) { - m_error.SetErrorToErrno (); - if (m_error.GetError() == EINVAL) + Error error; + error.SetErrorToErrno (); + if (error.GetError() == EINVAL) { // We may still have a shot at memory mapping if we align things correctly size_t page_offset = offset % Host::GetPageSize(); if (page_offset != 0) { - m_mmap_addr = (uint8_t *)::mmap(NULL, length + page_offset, PROT_READ, MAP_FILE | MAP_SHARED, fd, offset - page_offset); + m_mmap_addr = (uint8_t *)::mmap(NULL, length + page_offset, prot, flags, fd, offset - page_offset); if (m_mmap_addr == (void*)-1) { // Failed to map file @@ -188,7 +202,6 @@ DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, off_t offset, size_t l { // We recovered and were able to memory map // after we aligned things to page boundaries - m_error.Clear (); // Save the actual mmap'ed size m_mmap_size = length + page_offset; diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 551863e73d4..a6bcb9bf07e 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -201,6 +201,9 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args) { m_gdb_client.QueryNoAckModeSupported(); m_gdb_client.GetHostInfo(); +#if 0 + m_gdb_client.TestPacketSpeed(10000); +#endif } else { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 39efd359905..d0198a0db09 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -765,9 +765,9 @@ GDBRemoteCommunicationClient::GetSystemArchitecture () bool -GDBRemoteCommunicationClient::GetHostInfo () +GDBRemoteCommunicationClient::GetHostInfo (bool force) { - if (m_qHostInfo_is_valid == eLazyBoolCalculate) + if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) { m_qHostInfo_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; @@ -1363,5 +1363,87 @@ GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name) } } return false; +} +void +GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets) +{ + uint32_t i; + TimeValue start_time, end_time; + uint64_t total_time_nsec; + float packets_per_second; + if (SendSpeedTestPacket (0, 0)) + { + for (uint32_t send_size = 0; send_size <= 1024; send_size *= 2) + { + for (uint32_t recv_size = 0; recv_size <= 1024; recv_size *= 2) + { + start_time = TimeValue::Now(); + for (i=0; i<num_packets; ++i) + { + SendSpeedTestPacket (send_size, recv_size); + } + end_time = TimeValue::Now(); + total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); + packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)NSEC_PER_SEC; + printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %llu.%09.9llu sec for %f packets/sec.\n", + num_packets, + send_size, + recv_size, + total_time_nsec / NSEC_PER_SEC, + total_time_nsec % NSEC_PER_SEC, + packets_per_second); + if (recv_size == 0) + recv_size = 32; + } + if (send_size == 0) + send_size = 32; + } + } + else + { + start_time = TimeValue::Now(); + for (i=0; i<num_packets; ++i) + { + GetCurrentProcessID (); + } + end_time = TimeValue::Now(); + total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970(); + packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)NSEC_PER_SEC; + printf ("%u 'qC' packets packets in 0x%llu%09.9llu sec for %f packets/sec.\n", + num_packets, + total_time_nsec / NSEC_PER_SEC, + total_time_nsec % NSEC_PER_SEC, + packets_per_second); + } +} + +bool +GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t recv_size) +{ + StreamString packet; + packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size); + uint32_t bytes_left = send_size; + while (bytes_left > 0) + { + if (bytes_left >= 26) + { + packet.PutCString("abcdefghijklmnopqrstuvwxyz"); + bytes_left -= 26; + } + else + { + packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); + bytes_left = 0; + } + } + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) + { + if (response.IsUnsupportedResponse()) + return false; + return true; + } + return false; } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index d28c8275bd4..ae1674a4d1f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -190,7 +190,7 @@ public: ResetDiscoverableSettings(); bool - GetHostInfo (); + GetHostInfo (bool force = false); bool GetOSVersion (uint32_t &major, @@ -246,6 +246,17 @@ public: return old_packet_timeout; } + void + TestPacketSpeed (const uint32_t num_packets); + + // This packet is for testing the speed of the interface only. Both + // the client and server need to support it, but this allows us to + // measure the packet speed without any other work being done on the + // other end and avoids any of that work affecting the packet send + // and response times. + bool + SendSpeedTestPacket (uint32_t send_size, + uint32_t recv_size); protected: //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index ea6842b999a..d6edbdd6a53 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -117,6 +117,8 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout case StringExtractorGDBRemote::eServerPacketType_qGroupName: return Handle_qGroupName (packet); + case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: + return Handle_qSpeedTest (packet); case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: return Handle_QStartNoAckMode (packet); } @@ -429,6 +431,42 @@ GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packe } bool +GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet) +{ + packet.SetFilePos(strlen ("qSpeedTest:")); + + std::string key; + std::string value; + bool success = packet.GetNameColonValue(key, value); + if (success && key.compare("response_size") == 0) + { + uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); + if (success) + { + if (response_size == 0) + return SendOKResponse(); + StreamString response; + uint32_t bytes_left = response_size; + response.PutCString("data:"); + while (bytes_left > 0) + { + if (bytes_left >= 26) + { + response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + bytes_left -= 26; + } + else + { + response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + bytes_left = 0; + } + } + return SendPacket (response); + } + } + return SendErrorResponse (7); +} +bool GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) { // Send response first before changing m_send_acks to we ack this packet diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 22fb7be4e9f..02440a2db96 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -86,6 +86,9 @@ protected: Handle_qGroupName (StringExtractorGDBRemote &packet); bool + Handle_qSpeedTest (StringExtractorGDBRemote &packet); + + bool Handle_QStartNoAckMode (StringExtractorGDBRemote &packet); private: diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index 67df31ab61b..3c0a9cab86f 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -81,7 +81,9 @@ StringExtractorGDBRemote::GetServerPacketType () const break; case 'q': - if (packet_cstr[1] == 'H' && 0 == ::strcmp (packet_cstr, "qHostInfo")) + if (packet_cstr[1] == 'S' && 0 == ::strncmp(packet_cstr, "qSpeedTest:", strlen("qSpeedTest:"))) + return eServerPacketType_qSpeedTest; + else if (packet_cstr[1] == 'H' && 0 == ::strcmp (packet_cstr, "qHostInfo")) return eServerPacketType_qHostInfo; else if (packet_cstr[1] == 'P' && 0 == ::strncmp(packet_cstr, "qProcessInfoPID:", strlen("qProcessInfoPID:"))) return eServerPacketType_qProcessInfoPID; diff --git a/lldb/source/Utility/StringExtractorGDBRemote.h b/lldb/source/Utility/StringExtractorGDBRemote.h index c0977a8854e..36fd0344a09 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.h +++ b/lldb/source/Utility/StringExtractorGDBRemote.h @@ -52,6 +52,7 @@ public: eServerPacketType_qsProcessInfo, eServerPacketType_qUserName, eServerPacketType_qGroupName, + eServerPacketType_qSpeedTest, eServerPacketType_QStartNoAckMode }; diff --git a/lldb/tools/lldb-platform/lldb-platform.cpp b/lldb/tools/lldb-platform/lldb-platform.cpp index 8e4174ec4e4..be8359717fa 100644 --- a/lldb/tools/lldb-platform/lldb-platform.cpp +++ b/lldb/tools/lldb-platform/lldb-platform.cpp @@ -21,6 +21,7 @@ // Other libraries and framework includes #include "lldb/Core/Error.h" #include "lldb/Core/ConnectionFileDescriptor.h" +#include "lldb/Core/ConnectionMachPort.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" #include "GDBRemoteCommunicationServer.h" @@ -70,11 +71,50 @@ main (int argc, char *argv[]) int long_option_index = 0; StreamSP log_stream_sp; Args log_args; + Error error; std::string listen_host_post; char ch; Debugger::Initialize(); - +// ConnectionMachPort a; +// ConnectionMachPort b; +// +// lldb::ConnectionStatus status; +// const char *bootstrap_service_name = "HelloWorld"; +// status = a.BootstrapCheckIn(bootstrap_service_name, &error); +// +// if (status != eConnectionStatusSuccess) +// { +// fprintf(stderr, "%s", error.AsCString()); +// return 1; +// } +// status = b.BootstrapLookup (bootstrap_service_name, &error); +// if (status != eConnectionStatusSuccess) +// { +// fprintf(stderr, "%s", error.AsCString()); +// return 2; +// } +// +// if (a.Write ("hello", 5, status, &error) == 5) +// { +// char buf[32]; +// memset(buf, 0, sizeof(buf)); +// if (b.Read (buf, 5, status, &error)) +// { +// printf("read returned bytes: %s", buf); +// } +// else +// { +// fprintf(stderr, "%s", error.AsCString()); +// return 4; +// } +// } +// else +// { +// fprintf(stderr, "%s", error.AsCString()); +// return 3; +// } + while ((ch = getopt_long(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1) { // DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", @@ -141,7 +181,6 @@ main (int argc, char *argv[]) GDBRemoteCommunicationServer gdb_server; - Error error; if (!listen_host_post.empty()) { std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor()); |