13
13
#include " PluginServer.h"
14
14
#include " swift/ABI/MetadataValues.h"
15
15
#include " swift/Demangling/Demangle.h"
16
+ #include " llvm/Support/DynamicLibrary.h"
16
17
18
+ #if defined(_WIN32)
19
+ #include < io.h>
20
+ #elif defined(__unix__) || defined(__APPLE__)
17
21
#include < dlfcn.h>
22
+ #include < unistd.h>
23
+ #endif
24
+
18
25
#include < errno.h>
19
26
#include < string.h>
20
- #include < unistd.h>
21
27
22
28
using namespace swift ;
23
29
@@ -32,6 +38,46 @@ struct ConnectionHandle {
32
38
} // namespace
33
39
34
40
const void *PluginServer_createConnection (const char **errorMessage) {
41
+ #if defined(_WIN32)
42
+ struct unique_fd {
43
+ unique_fd (int fd) : fd_(fd) {}
44
+ unique_fd (const unique_fd &) = delete ;
45
+ unique_fd &operator =(const unique_fd &) = delete ;
46
+ unique_fd &operator =(unique_fd &&) = delete ;
47
+ unique_fd (unique_fd &&uf) : fd_(uf.fd_) { uf.fd_ = -1 ; }
48
+ ~unique_fd () { if (fd_ > 0 ) _close (fd_); }
49
+
50
+ int operator *() const { return fd_; }
51
+ int release () { int fd = fd_; fd_ = -1 ; return fd; }
52
+
53
+ private:
54
+ int fd_;
55
+ };
56
+
57
+ unique_fd ifd{_dup (_fileno (stdin))};
58
+ if (*ifd < 0 ) {
59
+ *errorMessage = _strerror (nullptr );
60
+ return nullptr ;
61
+ }
62
+
63
+ if (_close (_fileno (stdin)) < 0 ) {
64
+ *errorMessage = _strerror (nullptr );
65
+ return nullptr ;
66
+ }
67
+
68
+ unique_fd ofd{_dup (_fileno (stdout))};
69
+ if (*ofd < 0 ) {
70
+ *errorMessage = _strerror (nullptr );
71
+ return nullptr ;
72
+ }
73
+
74
+ if (_dup2 (_fileno (stderr), _fileno (stdout)) < 0 ) {
75
+ *errorMessage = _strerror (nullptr );
76
+ return nullptr ;
77
+ }
78
+
79
+ return new ConnectionHandle (ifd.release (), ofd.release ());
80
+ #else
35
81
// Duplicate the `stdin` file descriptor, which we will then use for
36
82
// receiving messages from the plugin host.
37
83
auto inputFD = dup (STDIN_FILENO);
@@ -65,37 +111,48 @@ const void *PluginServer_createConnection(const char **errorMessage) {
65
111
66
112
// Open a message channel for communicating with the plugin host.
67
113
return new ConnectionHandle (inputFD, outputFD);
114
+ #endif
68
115
}
69
116
70
- void PluginServer_destroyConnection (const void *connHandle) {
71
- const auto *conn = static_cast <const ConnectionHandle *>(connHandle);
72
- delete conn;
117
+ void PluginServer_destroyConnection (const void *server) {
118
+ delete static_cast <const ConnectionHandle *>(server);
73
119
}
74
120
75
- long PluginServer_read (const void *connHandle, void *data,
76
- unsigned long nbyte) {
77
- const auto *conn = static_cast <const ConnectionHandle *>(connHandle);
78
- return ::read (conn->inputFD , data, nbyte);
121
+ size_t PluginServer_read (const void *server, void *data, size_t nbyte) {
122
+ const auto *connection = static_cast <const ConnectionHandle *>(server);
123
+ #if defined(_WIN32)
124
+ return _read (connection->inputFD , data, nbyte);
125
+ #else
126
+ return ::read (connection->inputFD , data, nbyte);
127
+ #endif
79
128
}
80
129
81
- long PluginServer_write (const void *connHandle, const void *data,
82
- unsigned long nbyte) {
83
- const auto *conn = static_cast <const ConnectionHandle *>(connHandle);
84
- return ::write (conn->outputFD , data, nbyte);
130
+ size_t PluginServer_write (const void *server, const void *data, size_t nbyte) {
131
+ const auto *connection = static_cast <const ConnectionHandle *>(server);
132
+ #if defined(_WIN32)
133
+ return _write (connection->outputFD , data, nbyte);
134
+ #else
135
+ return ::write (connection->outputFD , data, nbyte);
136
+ #endif
85
137
}
86
138
87
- void *PluginServer_dlopen (const char *filename, const char **errorMessage) {
88
- auto *handle = ::dlopen (filename, RTLD_LAZY | RTLD_LOCAL);
89
- if (!handle) {
90
- *errorMessage = dlerror ();
91
- }
92
- return handle;
139
+ void *PluginServer_load (const char *plugin, const char **errorMessage) {
140
+ // Use a static allocation for the error as the client will not release the
141
+ // string. POSIX 2008 (IEEE-1003.1-2008) specifies that it is implementation
142
+ // defined if `dlerror` is re-entrant. Take advantage of that and make it
143
+ // thread-unsafe. This ensures that the string outlives the call permitting
144
+ // the client to duplicate it.
145
+ static std::string error;
146
+ auto library = llvm::sys::DynamicLibrary::getLibrary (plugin, &error);
147
+ if (library.isValid ())
148
+ return library.getOSSpecificHandle ();
149
+ *errorMessage = error.c_str ();
150
+ return nullptr ;
93
151
}
94
152
95
153
const void *PluginServer_lookupMacroTypeMetadataByExternalName (
96
154
const char *moduleName, const char *typeName, void *libraryHint,
97
155
const char **errorMessage) {
98
-
99
156
// Look up the type metadata accessor as a struct, enum, or class.
100
157
const Demangle::Node::Kind typeKinds[] = {
101
158
Demangle::Node::Kind::Structure,
@@ -108,8 +165,12 @@ const void *PluginServer_lookupMacroTypeMetadataByExternalName(
108
165
auto symbolName =
109
166
mangledNameForTypeMetadataAccessor (moduleName, typeName, typeKind);
110
167
111
- auto *handle = libraryHint ? libraryHint : RTLD_DEFAULT;
112
- accessorAddr = ::dlsym (handle, symbolName.c_str ());
168
+ #if !defined(_WIN32)
169
+ if (libraryHint == nullptr )
170
+ libraryHint = RTLD_DEFAULT;
171
+ #endif
172
+ accessorAddr = llvm::sys::DynamicLibrary{libraryHint}
173
+ .getAddressOfSymbol (symbolName.c_str ());
113
174
if (accessorAddr)
114
175
break ;
115
176
}
0 commit comments