1 /* Copyright Joyent, Inc. and other Node contributors.
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:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
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.
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.
29 #pragma D depends_on library procfs.d
36 } node_dtrace_connection_t;
43 } node_dtrace_connection64_t;
52 translator node_connection_t <node_dtrace_connection_t *nc> {
53 fd = *(int32_t *)copyin((uintptr_t)&nc->fd, sizeof (int32_t));
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,
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));
68 * 32-bit and 64-bit structures received from node for HTTP client request
74 } node_dtrace_http_client_request_t;
79 } node_dtrace_http_client_request64_t;
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.
96 } node_dtrace_http_request_t;
102 } node_dtrace_http_server_request_t;
105 * Actual 32-bit and 64-bit, v0 and v1 structures received from node for the
106 * HTTP server request probe.
111 } node_dtrace_http_server_request_v0_t;
117 uint32_t forwardedFor;
118 } node_dtrace_http_server_request_v1_t;
123 } node_dtrace_http_server_request64_v0_t;
130 uint64_t forwardedFor;
131 } node_dtrace_http_server_request64_v1_t;
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.
142 } node_http_request_t;
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.
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.
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.
174 * Translate from node_dtrace_http_server_request_t (received from node 0.6 and
175 * later versions) to node_http_request_t.
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))));
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))));
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))));
224 * Translate from node_dtrace_http_client_request_t (received from node 0.6 and
225 * later versions) to node_http_request_t.
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))));
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))));
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.
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))));
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))));
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))));