src: deduplicate CHECK_EQ/CHECK_NE macros
[platform/upstream/nodejs.git] / src / node.d
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
23 /*
24  * This is the DTrace library file for the node provider, which includes
25  * the necessary translators to get from the args[] to something useful.
26  * Be warned:  the mechanics here are seriously ugly -- and one must always
27  * keep in mind that clean abstractions often require filthy systems.
28  */
29 #pragma D depends_on library procfs.d
30
31 typedef struct {
32         int32_t fd;
33         int32_t port;
34         uint32_t remote;
35         uint32_t buffered;
36 } node_dtrace_connection_t;
37
38 typedef struct {
39         int32_t fd;
40         int32_t port;
41         uint64_t remote;
42         uint32_t buffered;
43 } node_dtrace_connection64_t;
44
45 typedef struct {
46         int fd;
47         string remoteAddress;
48         int remotePort;
49         int bufferSize;
50 } node_connection_t;
51
52 translator node_connection_t <node_dtrace_connection_t *nc> {
53         fd = *(int32_t *)copyin((uintptr_t)&nc->fd, sizeof (int32_t));
54         remotePort =
55             *(int32_t *)copyin((uintptr_t)&nc->port, sizeof (int32_t));
56         remoteAddress = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
57             copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nc->remote,
58             sizeof (int32_t))) :
59             copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
60             &((node_dtrace_connection64_t *)nc)->remote, sizeof (int64_t)));
61         bufferSize = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
62             *(uint32_t *)copyin((uintptr_t)&nc->buffered, sizeof (int32_t)) :
63             *(uint32_t *)copyin((uintptr_t)
64             &((node_dtrace_connection64_t *)nc)->buffered, sizeof (int32_t));
65 };
66
67 /*
68  * 32-bit and 64-bit structures received from node for HTTP client request
69  * probe.
70  */
71 typedef struct {
72         uint32_t url;
73         uint32_t method;
74 } node_dtrace_http_client_request_t;
75
76 typedef struct {
77         uint64_t url;
78         uint64_t method;
79 } node_dtrace_http_client_request64_t;
80
81 /*
82  * The following structures are never used directly, but must exist to bind the
83  * types specified in the provider to the translators defined here.
84  * Ultimately, they always get cast to a more specific type inside the
85  * translator.  To add to the confusion, the DTrace compiler does not allow
86  * declaring two translators with the same destination type if the source types
87  * are structures with the same size (because libctf says they're compatible,
88  * so dtrace considers them equivalent).  Since we must define translators from
89  * node_dtrace_http_client_request_t (above), node_dtrace_http_request_t, and
90  * node_dtrace_http_server_request_t (both below), each of these three structs
91  * must be declared with a different size.
92  */
93 typedef struct {
94         uint32_t version;
95         uint64_t dummy1;
96 } node_dtrace_http_request_t;
97
98 typedef struct {
99         uint32_t version;
100         uint64_t dummy2;
101         uint64_t dummy3;
102 } node_dtrace_http_server_request_t;
103
104 /*
105  * Actual 32-bit and 64-bit, v0 and v1 structures received from node for the
106  * HTTP server request probe.
107  */
108 typedef struct {
109         uint32_t url;
110         uint32_t method;
111 } node_dtrace_http_server_request_v0_t;
112
113 typedef struct {
114         uint32_t version;
115         uint32_t url;
116         uint32_t method;
117         uint32_t forwardedFor;
118 } node_dtrace_http_server_request_v1_t;
119
120 typedef struct {
121         uint64_t url;
122         uint64_t method;
123 } node_dtrace_http_server_request64_v0_t;
124
125 typedef struct {
126         uint32_t version;
127         uint32_t pad;
128         uint64_t url;
129         uint64_t method;
130         uint64_t forwardedFor;
131 } node_dtrace_http_server_request64_v1_t;
132
133 /*
134  * In the end, both client and server request probes from both old and new
135  * binaries translate their arguments to node_http_request_t, which is what the
136  * user's D script ultimately sees.
137  */
138 typedef struct {
139         string url;
140         string method;
141         string forwardedFor;
142 } node_http_request_t;
143
144 /*
145  * The following translators are particularly filthy for reasons of backwards
146  * compatibility.  Stable versions of node prior to 0.6 used a single
147  * http_request struct with fields for "url" and "method" for both client and
148  * server probes.  0.6 added a "forwardedFor" field intended for the server
149  * probe only, and the http_request struct passed by the application was split
150  * first into client_http_request and server_http_request and the latter was
151  * again split for v0 (the old struct) and v1.
152  *
153  * To distinguish the binary representations of the two versions of these
154  * structs, the new version prepends a "version" member (where the old one has
155  * a "url" pointer).  Each field that we're translating below first switches on
156  * the value of this "version" field: if it's larger than 4096, we know we must
157  * be looking at the "url" pointer of the older structure version.  Otherwise,
158  * we must be looking at the new version.  Besides this, we have the usual
159  * switch based on the userland process data model.  This would all be simpler
160  * with macros, but those aren't available in D library files since we cannot
161  * rely on cpp being present at runtime.
162  *
163  * In retrospect, the versioning bit might have been unnecessary since the type
164  * of the object passed in should allow DTrace to select which translator to
165  * use.  However, DTrace does sometimes use translators whose source types
166  * don't quite match, and since we know this versioning logic works, we just
167  * leave it alone.  Each of the translators below is functionally identical
168  * (except that the client -> client translator doesn't bother translating
169  * forwardedFor) and should actually work with any version of any of the client
170  * or server structs transmitted by the application up to this point.
171  */
172
173 /*
174  * Translate from node_dtrace_http_server_request_t (received from node 0.6 and
175  * later versions) to node_http_request_t.
176  */
177 translator node_http_request_t <node_dtrace_http_server_request_t *nd> {
178         url = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
179                 sizeof (uint32_t))) >= 4096 ?
180             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
181                 copyinstr(*(uint32_t *)copyin((uintptr_t)
182                     &((node_dtrace_http_server_request_v0_t *)nd)->url,
183                     sizeof (uint32_t))) :
184                 copyinstr(*(uint64_t *)copyin((uintptr_t)
185                     &((node_dtrace_http_server_request64_v0_t *)nd)->url,
186                     sizeof (uint64_t)))) :
187             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
188                 copyinstr(*(uint32_t *)copyin((uintptr_t)
189                     &((node_dtrace_http_server_request_v1_t *)nd)->url,
190                     sizeof (uint32_t))) :
191                 copyinstr(*(uint64_t *)copyin((uintptr_t)
192                     &((node_dtrace_http_server_request64_v1_t *)nd)->url,
193                     sizeof (uint64_t))));
194
195         method = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
196                 sizeof (uint32_t))) >= 4096 ?
197             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
198                 copyinstr(*(uint32_t *)copyin((uintptr_t)
199                     &((node_dtrace_http_server_request_v0_t *)nd)->method,
200                     sizeof (uint32_t))) :
201                 copyinstr(*(uint64_t *)copyin((uintptr_t)
202                     &((node_dtrace_http_server_request64_v0_t *)nd)->method,
203                     sizeof (uint64_t)))) :
204             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
205                 copyinstr(*(uint32_t *)copyin((uintptr_t)
206                     &((node_dtrace_http_server_request_v1_t *)nd)->method,
207                     sizeof (uint32_t))) :
208                 copyinstr(*(uint64_t *)copyin((uintptr_t)
209                     &((node_dtrace_http_server_request64_v1_t *)nd)->method,
210                     sizeof (uint64_t))));
211
212         forwardedFor = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
213                 sizeof (uint32_t))) >= 4096 ? "" :
214             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
215                 copyinstr(*(uint32_t *)copyin((uintptr_t)
216                     &((node_dtrace_http_server_request_v1_t *)nd)->forwardedFor,
217                     sizeof (uint32_t))) :
218                 copyinstr(*(uint64_t *)copyin((uintptr_t)
219                     &((node_dtrace_http_server_request64_v1_t *)nd)->
220                     forwardedFor, sizeof (uint64_t))));
221 };
222
223 /*
224  * Translate from node_dtrace_http_client_request_t (received from node 0.6 and
225  * later versions) to node_http_request_t.
226  */
227 translator node_http_request_t <node_dtrace_http_client_request_t *nd> {
228         url = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
229                 sizeof (uint32_t))) >= 4096 ?
230             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
231                 copyinstr(*(uint32_t *)copyin((uintptr_t)
232                     &((node_dtrace_http_server_request_v0_t *)nd)->url,
233                     sizeof (uint32_t))) :
234                 copyinstr(*(uint64_t *)copyin((uintptr_t)
235                     &((node_dtrace_http_server_request64_v0_t *)nd)->url,
236                     sizeof (uint64_t)))) :
237             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
238                 copyinstr(*(uint32_t *)copyin((uintptr_t)
239                     &((node_dtrace_http_server_request_v1_t *)nd)->url,
240                     sizeof (uint32_t))) :
241                 copyinstr(*(uint64_t *)copyin((uintptr_t)
242                     &((node_dtrace_http_server_request64_v1_t *)nd)->url,
243                     sizeof (uint64_t))));
244
245         method = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
246                 sizeof (uint32_t))) >= 4096 ?
247             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
248                 copyinstr(*(uint32_t *)copyin((uintptr_t)
249                     &((node_dtrace_http_server_request_v0_t *)nd)->method,
250                     sizeof (uint32_t))) :
251                 copyinstr(*(uint64_t *)copyin((uintptr_t)
252                     &((node_dtrace_http_server_request64_v0_t *)nd)->method,
253                     sizeof (uint64_t)))) :
254             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
255                 copyinstr(*(uint32_t *)copyin((uintptr_t)
256                     &((node_dtrace_http_server_request_v1_t *)nd)->method,
257                     sizeof (uint32_t))) :
258                 copyinstr(*(uint64_t *)copyin((uintptr_t)
259                     &((node_dtrace_http_server_request64_v1_t *)nd)->method,
260                     sizeof (uint64_t))));
261
262         forwardedFor = "";
263 };
264
265 /*
266  * Translate from node_dtrace_http_request_t (received from versions of node
267  * prior to 0.6) to node_http_request_t.  This is used for both the server and
268  * client probes since these versions of node didn't distinguish between the
269  * types used in these probes.
270  */
271 translator node_http_request_t <node_dtrace_http_request_t *nd> {
272         url = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
273                 sizeof (uint32_t))) >= 4096 ?
274             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
275                 copyinstr(*(uint32_t *)copyin((uintptr_t)
276                     &((node_dtrace_http_server_request_v0_t *)nd)->url,
277                     sizeof (uint32_t))) :
278                 copyinstr(*(uint64_t *)copyin((uintptr_t)
279                     &((node_dtrace_http_server_request64_v0_t *)nd)->url,
280                     sizeof (uint64_t)))) :
281             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
282                 copyinstr(*(uint32_t *)copyin((uintptr_t)
283                     &((node_dtrace_http_server_request_v1_t *)nd)->url,
284                     sizeof (uint32_t))) :
285                 copyinstr(*(uint64_t *)copyin((uintptr_t)
286                     &((node_dtrace_http_server_request64_v1_t *)nd)->url,
287                     sizeof (uint64_t))));
288
289         method = (*(uint32_t *)copyin((uintptr_t)(uint32_t *)nd,
290                 sizeof (uint32_t))) >= 4096 ?
291             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
292                 copyinstr(*(uint32_t *)copyin((uintptr_t)
293                     &((node_dtrace_http_server_request_v0_t *)nd)->method,
294                     sizeof (uint32_t))) :
295                 copyinstr(*(uint64_t *)copyin((uintptr_t)
296                     &((node_dtrace_http_server_request64_v0_t *)nd)->method,
297                     sizeof (uint64_t)))) :
298             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
299                 copyinstr(*(uint32_t *)copyin((uintptr_t)
300                     &((node_dtrace_http_server_request_v1_t *)nd)->method,
301                     sizeof (uint32_t))) :
302                 copyinstr(*(uint64_t *)copyin((uintptr_t)
303                     &((node_dtrace_http_server_request64_v1_t *)nd)->method,
304                     sizeof (uint64_t))));
305
306         forwardedFor = (*(uint32_t *) copyin((uintptr_t)(uint32_t *)nd,
307                 sizeof (uint32_t))) >= 4096 ? "" :
308             (curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
309                 copyinstr(*(uint32_t *)copyin((uintptr_t)
310                     &((node_dtrace_http_server_request_v1_t *)nd)->forwardedFor,
311                     sizeof (uint32_t))) :
312                 copyinstr(*(uint64_t *)copyin((uintptr_t)
313                     &((node_dtrace_http_server_request64_v1_t *)nd)->
314                     forwardedFor, sizeof (uint64_t))));
315 };