• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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