1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #ifndef SRC_NODE_WIN32_ETW_PROVIDER_INL_H_
23 #define SRC_NODE_WIN32_ETW_PROVIDER_INL_H_
24
25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
26
27 #include "node_win32_etw_provider.h"
28 #include "node_etw_provider.h"
29
30 namespace node {
31
32 // From node_win32_etw_provider.cc
33 extern REGHANDLE node_provider;
34 extern EventWriteFunc event_write;
35 extern int events_enabled;
36
37 #define ETW_WRITE_STRING_DATA(data_descriptor, data) \
38 EventDataDescCreate(data_descriptor, \
39 data, \
40 (strlen(data) + 1) * sizeof(*data));
41
42 #define ETW_WRITE_INT32_DATA(data_descriptor, data) \
43 EventDataDescCreate(data_descriptor, data, sizeof(int32_t));
44
45 #define ETW_WRITE_INT64_DATA(data_descriptor, data) \
46 EventDataDescCreate(data_descriptor, data, sizeof(int64_t));
47
48 #define ETW_WRITE_ADDRESS_DATA(data_descriptor, data) \
49 EventDataDescCreate(data_descriptor, data, sizeof(intptr_t));
50
51 #define ETW_WRITE_INT16_DATA(data_descriptor, data) \
52 EventDataDescCreate(data_descriptor, data, sizeof(int16_t));
53
54 #define ETW_WRITE_WSTRING_DATA_LENGTH(data_descriptor, data, data_len_bytes) \
55 EventDataDescCreate(data_descriptor, \
56 data, \
57 data_len_bytes);
58
59 #define ETW_WRITE_NET_CONNECTION(descriptors, conn) \
60 ETW_WRITE_INT32_DATA(descriptors, &conn->fd); \
61 ETW_WRITE_INT32_DATA(descriptors + 1, &conn->port); \
62 ETW_WRITE_STRING_DATA(descriptors + 2, conn->remote); \
63 ETW_WRITE_INT32_DATA(descriptors + 3, &conn->buffered);
64
65 #define ETW_WRITE_HTTP_SERVER_REQUEST(descriptors, req) \
66 ETW_WRITE_STRING_DATA(descriptors, req->url); \
67 ETW_WRITE_STRING_DATA(descriptors + 1, req->method); \
68 ETW_WRITE_STRING_DATA(descriptors + 2, req->forwardedFor);
69
70 #define ETW_WRITE_HTTP_CLIENT_REQUEST(descriptors, req) \
71 ETW_WRITE_STRING_DATA(descriptors, req->url); \
72 ETW_WRITE_STRING_DATA(descriptors + 1, req->method);
73
74 #define ETW_WRITE_GC(descriptors, type, flags) \
75 ETW_WRITE_INT32_DATA(descriptors, &type); \
76 ETW_WRITE_INT32_DATA(descriptors + 1, &flags);
77
78 #define ETW_WRITE_V8ADDRESSCHANGE(descriptors, addr1, addr2) \
79 ETW_WRITE_ADDRESS_DATA(descriptors, &addr1); \
80 ETW_WRITE_ADDRESS_DATA(descriptors + 1, &addr2);
81
82 #define ETW_WRITE_JSMETHOD_LOADUNLOAD(descriptors, \
83 context, \
84 startAddr, \
85 size, \
86 id, \
87 flags, \
88 rangeId, \
89 sourceId, \
90 line, \
91 col, \
92 name, \
93 name_len_bytes) \
94 ETW_WRITE_ADDRESS_DATA(descriptors, &context); \
95 ETW_WRITE_ADDRESS_DATA(descriptors + 1, &startAddr); \
96 ETW_WRITE_INT64_DATA(descriptors + 2, &size); \
97 ETW_WRITE_INT32_DATA(descriptors + 3, &id); \
98 ETW_WRITE_INT16_DATA(descriptors + 4, &flags); \
99 ETW_WRITE_INT16_DATA(descriptors + 5, &rangeId); \
100 ETW_WRITE_INT64_DATA(descriptors + 6, &sourceId); \
101 ETW_WRITE_INT32_DATA(descriptors + 7, &line); \
102 ETW_WRITE_INT32_DATA(descriptors + 8, &col); \
103 ETW_WRITE_WSTRING_DATA_LENGTH(descriptors + 9, name, name_len_bytes);
104
105
106 #define ETW_WRITE_EVENT(eventDescriptor, dataDescriptors) \
107 DWORD status = event_write(node_provider, \
108 &eventDescriptor, \
109 sizeof(dataDescriptors) / \
110 sizeof(*dataDescriptors), \
111 dataDescriptors); \
112 CHECK_EQ(status, ERROR_SUCCESS);
113
114 // NOLINTNEXTLINE (readability/null_usage)
115 #define NULL_NOLINT NULL
116
117 #define ETW_WRITE_EMPTY_EVENT(eventDescriptor) \
118 DWORD status = event_write(node_provider, &eventDescriptor, 0, NULL_NOLINT); \
119 CHECK_EQ(status, ERROR_SUCCESS);
120
NODE_HTTP_SERVER_REQUEST(node_dtrace_http_server_request_t * req,node_dtrace_connection_t * conn,const char * remote,int port,const char * method,const char * url,int fd)121 void NODE_HTTP_SERVER_REQUEST(node_dtrace_http_server_request_t* req,
122 node_dtrace_connection_t* conn, const char* remote, int port,
123 const char* method, const char* url, int fd) {
124 EVENT_DATA_DESCRIPTOR descriptors[7];
125 ETW_WRITE_HTTP_SERVER_REQUEST(descriptors, req);
126 ETW_WRITE_NET_CONNECTION(descriptors + 3, conn);
127 ETW_WRITE_EVENT(NODE_HTTP_SERVER_REQUEST_EVENT, descriptors);
128 }
129
130
NODE_HTTP_SERVER_RESPONSE(node_dtrace_connection_t * conn,const char * remote,int port,int fd)131 void NODE_HTTP_SERVER_RESPONSE(node_dtrace_connection_t* conn,
132 const char* remote, int port, int fd) {
133 EVENT_DATA_DESCRIPTOR descriptors[4];
134 ETW_WRITE_NET_CONNECTION(descriptors, conn);
135 ETW_WRITE_EVENT(NODE_HTTP_SERVER_RESPONSE_EVENT, descriptors);
136 }
137
138
NODE_HTTP_CLIENT_REQUEST(node_dtrace_http_client_request_t * req,node_dtrace_connection_t * conn,const char * remote,int port,const char * method,const char * url,int fd)139 void NODE_HTTP_CLIENT_REQUEST(node_dtrace_http_client_request_t* req,
140 node_dtrace_connection_t* conn, const char* remote, int port,
141 const char* method, const char* url, int fd) {
142 EVENT_DATA_DESCRIPTOR descriptors[6];
143 ETW_WRITE_HTTP_CLIENT_REQUEST(descriptors, req);
144 ETW_WRITE_NET_CONNECTION(descriptors + 2, conn);
145 ETW_WRITE_EVENT(NODE_HTTP_CLIENT_REQUEST_EVENT, descriptors);
146 }
147
148
NODE_HTTP_CLIENT_RESPONSE(node_dtrace_connection_t * conn,const char * remote,int port,int fd)149 void NODE_HTTP_CLIENT_RESPONSE(node_dtrace_connection_t* conn,
150 const char* remote, int port, int fd) {
151 EVENT_DATA_DESCRIPTOR descriptors[4];
152 ETW_WRITE_NET_CONNECTION(descriptors, conn);
153 ETW_WRITE_EVENT(NODE_HTTP_CLIENT_RESPONSE_EVENT, descriptors);
154 }
155
156
NODE_NET_SERVER_CONNECTION(node_dtrace_connection_t * conn,const char * remote,int port,int fd)157 void NODE_NET_SERVER_CONNECTION(node_dtrace_connection_t* conn,
158 const char* remote, int port, int fd) {
159 EVENT_DATA_DESCRIPTOR descriptors[4];
160 ETW_WRITE_NET_CONNECTION(descriptors, conn);
161 ETW_WRITE_EVENT(NODE_NET_SERVER_CONNECTION_EVENT, descriptors);
162 }
163
164
NODE_NET_STREAM_END(node_dtrace_connection_t * conn,const char * remote,int port,int fd)165 void NODE_NET_STREAM_END(node_dtrace_connection_t* conn,
166 const char* remote, int port, int fd) {
167 EVENT_DATA_DESCRIPTOR descriptors[4];
168 ETW_WRITE_NET_CONNECTION(descriptors, conn);
169 ETW_WRITE_EVENT(NODE_NET_STREAM_END_EVENT, descriptors);
170 }
171
172
NODE_GC_START(v8::GCType type,v8::GCCallbackFlags flags,v8::Isolate * isolate)173 void NODE_GC_START(v8::GCType type,
174 v8::GCCallbackFlags flags,
175 v8::Isolate* isolate) {
176 if (events_enabled > 0) {
177 EVENT_DATA_DESCRIPTOR descriptors[2];
178 ETW_WRITE_GC(descriptors, type, flags);
179 ETW_WRITE_EVENT(NODE_GC_START_EVENT, descriptors);
180 }
181 }
182
183
NODE_GC_DONE(v8::GCType type,v8::GCCallbackFlags flags,v8::Isolate * isolate)184 void NODE_GC_DONE(v8::GCType type,
185 v8::GCCallbackFlags flags,
186 v8::Isolate* isolate) {
187 if (events_enabled > 0) {
188 EVENT_DATA_DESCRIPTOR descriptors[2];
189 ETW_WRITE_GC(descriptors, type, flags);
190 ETW_WRITE_EVENT(NODE_GC_DONE_EVENT, descriptors);
191 }
192 }
193
194
NODE_V8SYMBOL_REMOVE(const void * addr1,const void * addr2)195 void NODE_V8SYMBOL_REMOVE(const void* addr1, const void* addr2) {
196 if (events_enabled > 0) {
197 EVENT_DATA_DESCRIPTOR descriptors[2];
198 ETW_WRITE_V8ADDRESSCHANGE(descriptors, addr1, addr2);
199 ETW_WRITE_EVENT(NODE_V8SYMBOL_REMOVE_EVENT, descriptors);
200 }
201 }
202
203
NODE_V8SYMBOL_MOVE(const void * addr1,const void * addr2)204 void NODE_V8SYMBOL_MOVE(const void* addr1, const void* addr2) {
205 if (events_enabled > 0) {
206 EVENT_DATA_DESCRIPTOR descriptors[2];
207 ETW_WRITE_V8ADDRESSCHANGE(descriptors, addr1, addr2);
208 ETW_WRITE_EVENT(NODE_V8SYMBOL_MOVE_EVENT, descriptors);
209 }
210 }
211
212
NODE_V8SYMBOL_RESET()213 void NODE_V8SYMBOL_RESET() {
214 if (events_enabled > 0) {
215 ETW_WRITE_EMPTY_EVENT(NODE_V8SYMBOL_RESET_EVENT);
216 }
217 }
218
219 #define SETSYMBUF(s) \
220 wcscpy(symbuf, s); \
221 symbol_len = arraysize(s) - 1;
222
NODE_V8SYMBOL_ADD(LPCSTR symbol,int symbol_len,const void * addr1,int len)223 void NODE_V8SYMBOL_ADD(LPCSTR symbol,
224 int symbol_len,
225 const void* addr1,
226 int len) {
227 if (events_enabled > 0) {
228 wchar_t symbuf[128];
229 if (symbol == nullptr) {
230 SETSYMBUF(L"nullptr");
231 } else {
232 symbol_len = MultiByteToWideChar(CP_ACP,
233 0,
234 symbol,
235 symbol_len,
236 symbuf,
237 128);
238 if (symbol_len == 0) {
239 SETSYMBUF(L"Invalid");
240 } else {
241 if (symbol_len > 127) {
242 symbol_len = 127;
243 }
244 symbuf[symbol_len] = L'\0';
245 }
246 }
247 void* context = nullptr;
248 INT64 size = (INT64)len;
249 INT32 id = (INT32)addr1;
250 INT16 flags = 0;
251 INT16 rangeid = 1;
252 INT32 col = 1;
253 INT32 line = 1;
254 INT64 sourceid = 0;
255 EVENT_DATA_DESCRIPTOR descriptors[10];
256 ETW_WRITE_JSMETHOD_LOADUNLOAD(descriptors,
257 context,
258 addr1,
259 size,
260 id,
261 flags,
262 rangeid,
263 sourceid,
264 line,
265 col,
266 symbuf,
267 (symbol_len + 1) * sizeof(symbuf[0]));
268 ETW_WRITE_EVENT(MethodLoad, descriptors);
269 }
270 }
271 #undef SETSYMBUF
272
273 #undef NULL_NOLINT
274
275
NODE_HTTP_SERVER_REQUEST_ENABLED()276 bool NODE_HTTP_SERVER_REQUEST_ENABLED() { return events_enabled > 0; }
NODE_HTTP_SERVER_RESPONSE_ENABLED()277 bool NODE_HTTP_SERVER_RESPONSE_ENABLED() { return events_enabled > 0; }
NODE_HTTP_CLIENT_REQUEST_ENABLED()278 bool NODE_HTTP_CLIENT_REQUEST_ENABLED() { return events_enabled > 0; }
NODE_HTTP_CLIENT_RESPONSE_ENABLED()279 bool NODE_HTTP_CLIENT_RESPONSE_ENABLED() { return events_enabled > 0; }
NODE_NET_SERVER_CONNECTION_ENABLED()280 bool NODE_NET_SERVER_CONNECTION_ENABLED() { return events_enabled > 0; }
NODE_NET_STREAM_END_ENABLED()281 bool NODE_NET_STREAM_END_ENABLED() { return events_enabled > 0; }
NODE_V8SYMBOL_ENABLED()282 bool NODE_V8SYMBOL_ENABLED() { return events_enabled > 0; }
283
284 } // namespace node
285
286 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
287
288 #endif // SRC_NODE_WIN32_ETW_PROVIDER_INL_H_
289