Skip to content

Commit 488eeb3

Browse files
Fix connecting via abstract socket (llvm#136466)
Commit 82ee31f and Commit 2e89312 added socket sharing, but only for unix domain sockets. That broke Android, which uses unix-abstract sockets.
1 parent 6957699 commit 488eeb3

File tree

6 files changed

+97
-21
lines changed

6 files changed

+97
-21
lines changed

lldb/include/lldb/Host/linux/AbstractSocket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace lldb_private {
1515
class AbstractSocket : public DomainSocket {
1616
public:
1717
AbstractSocket();
18+
AbstractSocket(NativeSocket socket, bool should_close);
1819

1920
protected:
2021
size_t GetNameOffset() const override;

lldb/include/lldb/Host/posix/DomainSocket.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ class DomainSocket : public Socket {
3131

3232
std::vector<std::string> GetListeningConnectionURI() const override;
3333

34+
static llvm::Expected<std::unique_ptr<DomainSocket>>
35+
FromBoundNativeSocket(NativeSocket sockfd, bool should_close);
36+
3437
protected:
3538
DomainSocket(SocketProtocol protocol);
39+
DomainSocket(SocketProtocol protocol, NativeSocket socket, bool should_close);
3640

3741
virtual size_t GetNameOffset() const;
3842
virtual void DeleteSocketFile(llvm::StringRef name);

lldb/source/Host/linux/AbstractSocket.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ using namespace lldb_private;
1515

1616
AbstractSocket::AbstractSocket() : DomainSocket(ProtocolUnixAbstract) {}
1717

18+
AbstractSocket::AbstractSocket(NativeSocket socket, bool should_close)
19+
: DomainSocket(ProtocolUnixAbstract, socket, should_close) {}
20+
1821
size_t AbstractSocket::GetNameOffset() const { return 1; }
1922

2023
void AbstractSocket::DeleteSocketFile(llvm::StringRef name) {}

lldb/source/Host/posix/DomainSocket.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#include "lldb/Host/posix/DomainSocket.h"
1010
#include "lldb/Utility/LLDBLog.h"
11+
#ifdef __linux__
12+
#include <lldb/Host/linux/AbstractSocket.h>
13+
#endif
1114

1215
#include "llvm/Support/Errno.h"
1316
#include "llvm/Support/FileSystem.h"
@@ -67,6 +70,12 @@ DomainSocket::DomainSocket(NativeSocket socket,
6770
m_socket = socket;
6871
}
6972

73+
DomainSocket::DomainSocket(SocketProtocol protocol, NativeSocket socket,
74+
bool should_close)
75+
: Socket(protocol, should_close) {
76+
m_socket = socket;
77+
}
78+
7079
Status DomainSocket::Connect(llvm::StringRef name) {
7180
sockaddr_un saddr_un;
7281
socklen_t saddr_un_len;
@@ -182,3 +191,20 @@ std::vector<std::string> DomainSocket::GetListeningConnectionURI() const {
182191

183192
return {llvm::formatv("unix-connect://{0}", addr.sun_path)};
184193
}
194+
195+
llvm::Expected<std::unique_ptr<DomainSocket>>
196+
DomainSocket::FromBoundNativeSocket(NativeSocket sockfd, bool should_close) {
197+
// Check if fd represents domain socket or abstract socket.
198+
struct sockaddr_un addr;
199+
socklen_t addr_len = sizeof(addr);
200+
if (getsockname(sockfd, (struct sockaddr *)&addr, &addr_len) == -1)
201+
return llvm::createStringError("not a socket or error occurred");
202+
if (addr.sun_family != AF_UNIX)
203+
return llvm::createStringError("Bad socket type");
204+
#ifdef __linux__
205+
if (addr_len > offsetof(struct sockaddr_un, sun_path) &&
206+
addr.sun_path[0] == '\0')
207+
return std::make_unique<AbstractSocket>(sockfd, should_close);
208+
#endif
209+
return std::make_unique<DomainSocket>(sockfd, should_close);
210+
}

lldb/tools/lldb-server/lldb-platform.cpp

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -455,37 +455,34 @@ int main_platform(int argc, char *argv[]) {
455455
lldb_private::Args inferior_arguments;
456456
inferior_arguments.SetArguments(argc, const_cast<const char **>(argv));
457457

458-
Socket::SocketProtocol protocol = Socket::ProtocolUnixDomain;
459-
458+
Log *log = GetLog(LLDBLog::Platform);
460459
if (fd != SharedSocket::kInvalidFD) {
461460
// Child process will handle the connection and exit.
462-
if (gdbserver_port)
463-
protocol = Socket::ProtocolTcp;
464-
465-
Log *log = GetLog(LLDBLog::Platform);
466-
467461
NativeSocket sockfd;
468462
error = SharedSocket::GetNativeSocket(fd, sockfd);
469463
if (error.Fail()) {
470464
LLDB_LOGF(log, "lldb-platform child: %s", error.AsCString());
471465
return socket_error;
472466
}
473467

474-
GDBRemoteCommunicationServerPlatform platform(protocol, gdbserver_port);
475-
Socket *socket;
476-
if (protocol == Socket::ProtocolTcp)
477-
socket = new TCPSocket(sockfd, /*should_close=*/true);
478-
else {
479-
#if LLDB_ENABLE_POSIX
480-
socket = new DomainSocket(sockfd, /*should_close=*/true);
481-
#else
482-
WithColor::error() << "lldb-platform child: Unix domain sockets are not "
483-
"supported on this platform.";
484-
return socket_error;
485-
#endif
468+
std::unique_ptr<Socket> socket;
469+
if (gdbserver_port) {
470+
socket = std::make_unique<TCPSocket>(sockfd, /*should_close=*/true);
471+
} else {
472+
llvm::Expected<std::unique_ptr<DomainSocket>> domain_socket =
473+
DomainSocket::FromBoundNativeSocket(sockfd, /*should_close=*/true);
474+
if (!domain_socket) {
475+
LLDB_LOG_ERROR(log, domain_socket.takeError(),
476+
"Failed to create socket: {0}");
477+
return socket_error;
478+
}
479+
socket = std::move(domain_socket.get());
486480
}
487-
platform.SetConnection(
488-
std::unique_ptr<Connection>(new ConnectionFileDescriptor(socket)));
481+
482+
GDBRemoteCommunicationServerPlatform platform(socket->GetSocketProtocol(),
483+
gdbserver_port);
484+
platform.SetConnection(std::unique_ptr<Connection>(
485+
new ConnectionFileDescriptor(socket.release())));
489486
client_handle(platform, inferior_arguments);
490487
return 0;
491488
}
@@ -498,6 +495,7 @@ int main_platform(int argc, char *argv[]) {
498495
return 1;
499496
}
500497

498+
Socket::SocketProtocol protocol = Socket::ProtocolUnixDomain;
501499
std::string address;
502500
std::string gdb_address;
503501
uint16_t platform_port = 0;

lldb/unittests/Host/SocketTest.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "gmock/gmock.h"
1616
#include "gtest/gtest.h"
1717
#include <chrono>
18+
#if __linux__
19+
#include <lldb/Host/linux/AbstractSocket.h>
20+
#endif
1821

1922
using namespace lldb_private;
2023

@@ -337,6 +340,47 @@ TEST_F(SocketTest, DomainGetConnectURI) {
337340

338341
EXPECT_EQ(socket_b_up->GetRemoteConnectionURI(), "");
339342
}
343+
344+
TEST_F(SocketTest, DomainSocketFromBoundNativeSocket) {
345+
// Generate a name for the domain socket.
346+
llvm::SmallString<64> name;
347+
std::error_code EC = llvm::sys::fs::createUniqueDirectory(
348+
"DomainSocketFromBoundNativeSocket", name);
349+
ASSERT_FALSE(EC);
350+
llvm::sys::path::append(name, "test");
351+
352+
DomainSocket socket(true);
353+
Status error = socket.Listen(name, /*backlog=*/10);
354+
ASSERT_THAT_ERROR(error.takeError(), llvm::Succeeded());
355+
NativeSocket native_socket = socket.GetNativeSocket();
356+
357+
llvm::Expected<std::unique_ptr<DomainSocket>> sock =
358+
DomainSocket::FromBoundNativeSocket(native_socket,
359+
/*should_close=*/false);
360+
ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
361+
ASSERT_EQ(Socket::ProtocolUnixDomain, sock->get()->GetSocketProtocol());
362+
}
363+
#endif
364+
365+
#if __linux__
366+
TEST_F(SocketTest, AbstractSocketFromBoundNativeSocket) {
367+
// Generate a name for the abstract socket.
368+
llvm::SmallString<100> name;
369+
llvm::sys::fs::createUniquePath("AbstractSocketFromBoundNativeSocket", name,
370+
true);
371+
llvm::sys::path::append(name, "test");
372+
373+
AbstractSocket socket;
374+
Status error = socket.Listen(name, /*backlog=*/10);
375+
ASSERT_THAT_ERROR(error.takeError(), llvm::Succeeded());
376+
NativeSocket native_socket = socket.GetNativeSocket();
377+
378+
llvm::Expected<std::unique_ptr<DomainSocket>> sock =
379+
DomainSocket::FromBoundNativeSocket(native_socket,
380+
/*should_close=*/false);
381+
ASSERT_THAT_EXPECTED(sock, llvm::Succeeded());
382+
ASSERT_EQ(Socket::ProtocolUnixAbstract, sock->get()->GetSocketProtocol());
383+
}
340384
#endif
341385

342386
INSTANTIATE_TEST_SUITE_P(

0 commit comments

Comments
 (0)