Commit | Line | Data |
---|---|---|
d4777acb JM |
1 | /* DTrace probe support for GDB. |
2 | ||
61baf725 | 3 | Copyright (C) 2014-2017 Free Software Foundation, Inc. |
d4777acb JM |
4 | |
5 | Contributed by Oracle, Inc. | |
6 | ||
7 | This file is part of GDB. | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 3 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
21 | ||
22 | #include "defs.h" | |
23 | #include "probe.h" | |
24 | #include "vec.h" | |
25 | #include "elf-bfd.h" | |
26 | #include "gdbtypes.h" | |
27 | #include "obstack.h" | |
28 | #include "objfiles.h" | |
29 | #include "complaints.h" | |
30 | #include "value.h" | |
31 | #include "ax.h" | |
32 | #include "ax-gdb.h" | |
33 | #include "language.h" | |
34 | #include "parser-defs.h" | |
35 | #include "inferior.h" | |
36 | ||
37 | /* The type of the ELF sections where we will find the DOF programs | |
38 | with information about probes. */ | |
39 | ||
40 | #ifndef SHT_SUNW_dof | |
41 | # define SHT_SUNW_dof 0x6ffffff4 | |
42 | #endif | |
43 | ||
44 | /* Forward declaration. */ | |
45 | ||
bf36a1e7 | 46 | extern const struct probe_ops dtrace_probe_ops; |
d4777acb JM |
47 | |
48 | /* The following structure represents a single argument for the | |
49 | probe. */ | |
50 | ||
51 | struct dtrace_probe_arg | |
52 | { | |
53 | /* The type of the probe argument. */ | |
54 | struct type *type; | |
55 | ||
56 | /* A string describing the type. */ | |
57 | char *type_str; | |
58 | ||
59 | /* The argument converted to an internal GDB expression. */ | |
60 | struct expression *expr; | |
61 | }; | |
62 | ||
63 | typedef struct dtrace_probe_arg dtrace_probe_arg_s; | |
64 | DEF_VEC_O (dtrace_probe_arg_s); | |
65 | ||
66 | /* The following structure represents an enabler for a probe. */ | |
67 | ||
68 | struct dtrace_probe_enabler | |
69 | { | |
70 | /* Program counter where the is-enabled probe is installed. The | |
71 | contents (nops, whatever...) stored at this address are | |
72 | architecture dependent. */ | |
73 | CORE_ADDR address; | |
74 | }; | |
75 | ||
76 | typedef struct dtrace_probe_enabler dtrace_probe_enabler_s; | |
77 | DEF_VEC_O (dtrace_probe_enabler_s); | |
78 | ||
79 | /* The following structure represents a dtrace probe. */ | |
80 | ||
81 | struct dtrace_probe | |
82 | { | |
83 | /* Generic information about the probe. This must be the first | |
84 | element of this struct, in order to maintain binary compatibility | |
85 | with the `struct probe' and be able to fully abstract it. */ | |
86 | struct probe p; | |
87 | ||
88 | /* A probe can have zero or more arguments. */ | |
89 | int probe_argc; | |
90 | VEC (dtrace_probe_arg_s) *args; | |
91 | ||
92 | /* A probe can have zero or more "enablers" associated with it. */ | |
93 | VEC (dtrace_probe_enabler_s) *enablers; | |
94 | ||
95 | /* Whether the expressions for the arguments have been built. */ | |
96 | unsigned int args_expr_built : 1; | |
97 | }; | |
98 | ||
99 | /* Implementation of the probe_is_linespec method. */ | |
100 | ||
101 | static int | |
102 | dtrace_probe_is_linespec (const char **linespecp) | |
103 | { | |
104 | static const char *const keywords[] = { "-pdtrace", "-probe-dtrace", NULL }; | |
105 | ||
106 | return probe_is_linespec_by_keyword (linespecp, keywords); | |
107 | } | |
108 | ||
109 | /* DOF programs can contain an arbitrary number of sections of 26 | |
110 | different types. In order to support DTrace USDT probes we only | |
111 | need to handle a subset of these section types, fortunately. These | |
112 | section types are defined in the following enumeration. | |
113 | ||
114 | See linux/dtrace/dof_defines.h for a complete list of section types | |
115 | along with their values. */ | |
116 | ||
117 | enum dtrace_dof_sect_type | |
118 | { | |
119 | /* Null section. */ | |
120 | DTRACE_DOF_SECT_TYPE_NONE = 0, | |
121 | /* A dof_ecbdesc_t. */ | |
122 | DTRACE_DOF_SECT_TYPE_ECBDESC = 3, | |
123 | /* A string table. */ | |
124 | DTRACE_DOF_SECT_TYPE_STRTAB = 8, | |
125 | /* A dof_provider_t */ | |
126 | DTRACE_DOF_SECT_TYPE_PROVIDER = 15, | |
127 | /* Array of dof_probe_t */ | |
128 | DTRACE_DOF_SECT_TYPE_PROBES = 16, | |
129 | /* An array of probe arg mappings. */ | |
130 | DTRACE_DOF_SECT_TYPE_PRARGS = 17, | |
131 | /* An array of probe arg offsets. */ | |
132 | DTRACE_DOF_SECT_TYPE_PROFFS = 18, | |
133 | /* An array of probe is-enabled offsets. */ | |
134 | DTRACE_DOF_SECT_TYPE_PRENOFFS = 26 | |
135 | }; | |
136 | ||
137 | /* The following collection of data structures map the structure of | |
138 | DOF entities. Again, we only cover the subset of DOF used to | |
139 | implement USDT probes. | |
140 | ||
141 | See linux/dtrace/dof.h header for a complete list of data | |
142 | structures. */ | |
143 | ||
144 | /* Offsets to index the dofh_ident[] array defined below. */ | |
145 | ||
146 | enum dtrace_dof_ident | |
147 | { | |
148 | /* First byte of the magic number. */ | |
149 | DTRACE_DOF_ID_MAG0 = 0, | |
150 | /* Second byte of the magic number. */ | |
151 | DTRACE_DOF_ID_MAG1 = 1, | |
152 | /* Third byte of the magic number. */ | |
153 | DTRACE_DOF_ID_MAG2 = 2, | |
154 | /* Fourth byte of the magic number. */ | |
155 | DTRACE_DOF_ID_MAG3 = 3, | |
156 | /* An enum_dof_encoding value. */ | |
157 | DTRACE_DOF_ID_ENCODING = 5 | |
158 | }; | |
159 | ||
160 | /* Possible values for dofh_ident[DOF_ID_ENCODING]. */ | |
161 | ||
162 | enum dtrace_dof_encoding | |
163 | { | |
164 | /* The DOF program is little-endian. */ | |
165 | DTRACE_DOF_ENCODE_LSB = 1, | |
166 | /* The DOF program is big-endian. */ | |
167 | DTRACE_DOF_ENCODE_MSB = 2 | |
168 | }; | |
169 | ||
170 | /* A DOF header, which describes the contents of a DOF program: number | |
171 | of sections, size, etc. */ | |
172 | ||
173 | struct dtrace_dof_hdr | |
174 | { | |
175 | /* Identification bytes (see above). */ | |
176 | uint8_t dofh_ident[16]; | |
177 | /* File attribute flags (if any). */ | |
178 | uint32_t dofh_flags; | |
179 | /* Size of file header in bytes. */ | |
180 | uint32_t dofh_hdrsize; | |
181 | /* Size of section header in bytes. */ | |
182 | uint32_t dofh_secsize; | |
183 | /* Number of section headers. */ | |
184 | uint32_t dofh_secnum; | |
185 | /* File offset of section headers. */ | |
186 | uint64_t dofh_secoff; | |
187 | /* File size of loadable portion. */ | |
188 | uint64_t dofh_loadsz; | |
189 | /* File size of entire DOF file. */ | |
190 | uint64_t dofh_filesz; | |
191 | /* Reserved for future use. */ | |
192 | uint64_t dofh_pad; | |
193 | }; | |
194 | ||
195 | /* A DOF section, whose contents depend on its type. The several | |
196 | supported section types are described in the enum | |
197 | dtrace_dof_sect_type above. */ | |
198 | ||
199 | struct dtrace_dof_sect | |
200 | { | |
201 | /* Section type (see the define above). */ | |
202 | uint32_t dofs_type; | |
203 | /* Section data memory alignment. */ | |
204 | uint32_t dofs_align; | |
205 | /* Section flags (if any). */ | |
206 | uint32_t dofs_flags; | |
207 | /* Size of section entry (if table). */ | |
208 | uint32_t dofs_entsize; | |
209 | /* DOF + offset points to the section data. */ | |
210 | uint64_t dofs_offset; | |
211 | /* Size of section data in bytes. */ | |
212 | uint64_t dofs_size; | |
213 | }; | |
214 | ||
215 | /* A DOF provider, which is the provider of a probe. */ | |
216 | ||
217 | struct dtrace_dof_provider | |
218 | { | |
219 | /* Link to a DTRACE_DOF_SECT_TYPE_STRTAB section. */ | |
220 | uint32_t dofpv_strtab; | |
221 | /* Link to a DTRACE_DOF_SECT_TYPE_PROBES section. */ | |
222 | uint32_t dofpv_probes; | |
223 | /* Link to a DTRACE_DOF_SECT_TYPE_PRARGS section. */ | |
224 | uint32_t dofpv_prargs; | |
225 | /* Link to a DTRACE_DOF_SECT_TYPE_PROFFS section. */ | |
226 | uint32_t dofpv_proffs; | |
227 | /* Provider name string. */ | |
228 | uint32_t dofpv_name; | |
229 | /* Provider attributes. */ | |
230 | uint32_t dofpv_provattr; | |
231 | /* Module attributes. */ | |
232 | uint32_t dofpv_modattr; | |
233 | /* Function attributes. */ | |
234 | uint32_t dofpv_funcattr; | |
235 | /* Name attributes. */ | |
236 | uint32_t dofpv_nameattr; | |
237 | /* Args attributes. */ | |
238 | uint32_t dofpv_argsattr; | |
239 | /* Link to a DTRACE_DOF_SECT_PRENOFFS section. */ | |
240 | uint32_t dofpv_prenoffs; | |
241 | }; | |
242 | ||
243 | /* A set of DOF probes and is-enabled probes sharing a base address | |
244 | and several attributes. The particular locations and attributes of | |
245 | each probe are maintained in arrays in several other DOF sections. | |
246 | See the comment in dtrace_process_dof_probe for details on how | |
247 | these attributes are stored. */ | |
248 | ||
249 | struct dtrace_dof_probe | |
250 | { | |
251 | /* Probe base address or offset. */ | |
252 | uint64_t dofpr_addr; | |
253 | /* Probe function string. */ | |
254 | uint32_t dofpr_func; | |
255 | /* Probe name string. */ | |
256 | uint32_t dofpr_name; | |
257 | /* Native argument type strings. */ | |
258 | uint32_t dofpr_nargv; | |
259 | /* Translated argument type strings. */ | |
260 | uint32_t dofpr_xargv; | |
261 | /* Index of first argument mapping. */ | |
262 | uint32_t dofpr_argidx; | |
263 | /* Index of first offset entry. */ | |
264 | uint32_t dofpr_offidx; | |
265 | /* Native argument count. */ | |
266 | uint8_t dofpr_nargc; | |
267 | /* Translated argument count. */ | |
268 | uint8_t dofpr_xargc; | |
269 | /* Number of offset entries for probe. */ | |
270 | uint16_t dofpr_noffs; | |
271 | /* Index of first is-enabled offset. */ | |
272 | uint32_t dofpr_enoffidx; | |
273 | /* Number of is-enabled offsets. */ | |
274 | uint16_t dofpr_nenoffs; | |
275 | /* Reserved for future use. */ | |
276 | uint16_t dofpr_pad1; | |
277 | /* Reserved for future use. */ | |
278 | uint32_t dofpr_pad2; | |
279 | }; | |
280 | ||
281 | /* DOF supports two different encodings: MSB (big-endian) and LSB | |
282 | (little-endian). The encoding is itself encoded in the DOF header. | |
283 | The following function returns an unsigned value in the host | |
284 | endianness. */ | |
285 | ||
286 | #define DOF_UINT(dof, field) \ | |
287 | extract_unsigned_integer ((gdb_byte *) &(field), \ | |
288 | sizeof ((field)), \ | |
289 | (((dof)->dofh_ident[DTRACE_DOF_ID_ENCODING] \ | |
290 | == DTRACE_DOF_ENCODE_MSB) \ | |
291 | ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE)) | |
292 | ||
293 | /* The following macro applies a given byte offset to a DOF (a pointer | |
294 | to a dtrace_dof_hdr structure) and returns the resulting | |
295 | address. */ | |
296 | ||
297 | #define DTRACE_DOF_PTR(dof, offset) (&((char *) (dof))[(offset)]) | |
298 | ||
299 | /* The following macro returns a pointer to the beginning of a given | |
300 | section in a DOF object. The section is referred to by its index | |
301 | in the sections array. */ | |
302 | ||
303 | #define DTRACE_DOF_SECT(dof, idx) \ | |
304 | ((struct dtrace_dof_sect *) \ | |
305 | DTRACE_DOF_PTR ((dof), \ | |
306 | DOF_UINT ((dof), (dof)->dofh_secoff) \ | |
307 | + ((idx) * DOF_UINT ((dof), (dof)->dofh_secsize)))) | |
308 | ||
309 | /* Helper function to examine the probe described by the given PROBE | |
310 | and PROVIDER data structures and add it to the PROBESP vector. | |
311 | STRTAB, OFFTAB, EOFFTAB and ARGTAB are pointers to tables in the | |
312 | DOF program containing the attributes for the probe. */ | |
313 | ||
314 | static void | |
315 | dtrace_process_dof_probe (struct objfile *objfile, | |
aaa63a31 SM |
316 | struct gdbarch *gdbarch, |
317 | std::vector<probe *> *probesp, | |
d4777acb JM |
318 | struct dtrace_dof_hdr *dof, |
319 | struct dtrace_dof_probe *probe, | |
320 | struct dtrace_dof_provider *provider, | |
321 | char *strtab, char *offtab, char *eofftab, | |
322 | char *argtab, uint64_t strtab_size) | |
323 | { | |
324 | int i, j, num_probes, num_enablers; | |
325 | struct cleanup *cleanup; | |
326 | VEC (dtrace_probe_enabler_s) *enablers; | |
327 | char *p; | |
328 | ||
329 | /* Each probe section can define zero or more probes of two | |
330 | different types: | |
331 | ||
332 | - probe->dofpr_noffs regular probes whose program counters are | |
333 | stored in 32bit words starting at probe->dofpr_addr + | |
334 | offtab[probe->dofpr_offidx]. | |
335 | ||
336 | - probe->dofpr_nenoffs is-enabled probes whose program counters | |
337 | are stored in 32bit words starting at probe->dofpr_addr + | |
338 | eofftab[probe->dofpr_enoffidx]. | |
339 | ||
340 | However is-enabled probes are not probes per-se, but an | |
341 | optimization hack that is implemented in the kernel in a very | |
342 | similar way than normal probes. This is how we support | |
343 | is-enabled probes on GDB: | |
344 | ||
345 | - Our probes are always DTrace regular probes. | |
346 | ||
347 | - Our probes can be associated with zero or more "enablers". The | |
348 | list of enablers is built from the is-enabled probes defined in | |
349 | the Probe section. | |
350 | ||
351 | - Probes having a non-empty list of enablers can be enabled or | |
352 | disabled using the `enable probe' and `disable probe' commands | |
353 | respectively. The `Enabled' column in the output of `info | |
354 | probes' will read `yes' if the enablers are activated, `no' | |
355 | otherwise. | |
356 | ||
357 | - Probes having an empty list of enablers are always enabled. | |
358 | The `Enabled' column in the output of `info probes' will | |
359 | read `always'. | |
360 | ||
361 | It follows that if there are DTrace is-enabled probes defined for | |
362 | some provider/name but no DTrace regular probes defined then the | |
363 | GDB user wont be able to enable/disable these conditionals. */ | |
364 | ||
365 | num_probes = DOF_UINT (dof, probe->dofpr_noffs); | |
366 | if (num_probes == 0) | |
367 | return; | |
368 | ||
369 | /* Build the list of enablers for the probes defined in this Probe | |
370 | DOF section. */ | |
371 | enablers = NULL; | |
372 | cleanup | |
373 | = make_cleanup (VEC_cleanup (dtrace_probe_enabler_s), &enablers); | |
374 | num_enablers = DOF_UINT (dof, probe->dofpr_nenoffs); | |
375 | for (i = 0; i < num_enablers; i++) | |
376 | { | |
377 | struct dtrace_probe_enabler enabler; | |
378 | uint32_t enabler_offset | |
379 | = ((uint32_t *) eofftab)[DOF_UINT (dof, probe->dofpr_enoffidx) + i]; | |
380 | ||
381 | enabler.address = DOF_UINT (dof, probe->dofpr_addr) | |
382 | + DOF_UINT (dof, enabler_offset); | |
383 | VEC_safe_push (dtrace_probe_enabler_s, enablers, &enabler); | |
384 | } | |
385 | ||
386 | for (i = 0; i < num_probes; i++) | |
387 | { | |
388 | uint32_t probe_offset | |
389 | = ((uint32_t *) offtab)[DOF_UINT (dof, probe->dofpr_offidx) + i]; | |
8d749320 SM |
390 | struct dtrace_probe *ret = |
391 | XOBNEW (&objfile->per_bfd->storage_obstack, struct dtrace_probe); | |
d4777acb JM |
392 | |
393 | ret->p.pops = &dtrace_probe_ops; | |
394 | ret->p.arch = gdbarch; | |
395 | ret->args_expr_built = 0; | |
396 | ||
397 | /* Set the provider and the name of the probe. */ | |
398 | ret->p.provider | |
399 | = xstrdup (strtab + DOF_UINT (dof, provider->dofpv_name)); | |
400 | ret->p.name = xstrdup (strtab + DOF_UINT (dof, probe->dofpr_name)); | |
401 | ||
402 | /* The probe address. */ | |
403 | ret->p.address | |
404 | = DOF_UINT (dof, probe->dofpr_addr) + DOF_UINT (dof, probe_offset); | |
405 | ||
406 | /* Number of arguments in the probe. */ | |
407 | ret->probe_argc = DOF_UINT (dof, probe->dofpr_nargc); | |
408 | ||
409 | /* Store argument type descriptions. A description of the type | |
410 | of the argument is in the (J+1)th null-terminated string | |
411 | starting at 'strtab' + 'probe->dofpr_nargv'. */ | |
412 | ret->args = NULL; | |
413 | p = strtab + DOF_UINT (dof, probe->dofpr_nargv); | |
414 | for (j = 0; j < ret->probe_argc; j++) | |
415 | { | |
416 | struct dtrace_probe_arg arg; | |
4d01a485 | 417 | expression_up expr; |
d4777acb | 418 | |
ffdf88ec SE |
419 | /* Set arg.expr to ensure all fields in expr are initialized and |
420 | the compiler will not warn when arg is used. */ | |
421 | arg.expr = NULL; | |
d4777acb JM |
422 | arg.type_str = xstrdup (p); |
423 | ||
424 | /* Use strtab_size as a sentinel. */ | |
07809eaf SM |
425 | while (*p++ != '\0' && p - strtab < strtab_size) |
426 | ; | |
d4777acb JM |
427 | |
428 | /* Try to parse a type expression from the type string. If | |
429 | this does not work then we set the type to `long | |
430 | int'. */ | |
431 | arg.type = builtin_type (gdbarch)->builtin_long; | |
429e1e81 JB |
432 | |
433 | TRY | |
434 | { | |
036e657b | 435 | expr = parse_expression_with_language (arg.type_str, language_c); |
429e1e81 JB |
436 | } |
437 | CATCH (ex, RETURN_MASK_ERROR) | |
438 | { | |
429e1e81 JB |
439 | } |
440 | END_CATCH | |
441 | ||
442 | if (expr != NULL && expr->elts[0].opcode == OP_TYPE) | |
d4777acb JM |
443 | arg.type = expr->elts[1].type; |
444 | ||
445 | VEC_safe_push (dtrace_probe_arg_s, ret->args, &arg); | |
446 | } | |
447 | ||
448 | /* Add the vector of enablers to this probe, if any. */ | |
449 | ret->enablers = VEC_copy (dtrace_probe_enabler_s, enablers); | |
450 | ||
451 | /* Successfully created probe. */ | |
aaa63a31 | 452 | probesp->push_back ((struct probe *) ret); |
d4777acb JM |
453 | } |
454 | ||
455 | do_cleanups (cleanup); | |
456 | } | |
457 | ||
458 | /* Helper function to collect the probes described in the DOF program | |
459 | whose header is pointed by DOF and add them to the PROBESP vector. | |
460 | SECT is the ELF section containing the DOF program and OBJFILE is | |
461 | its containing object file. */ | |
462 | ||
463 | static void | |
464 | dtrace_process_dof (asection *sect, struct objfile *objfile, | |
aaa63a31 | 465 | std::vector<probe *> *probesp, struct dtrace_dof_hdr *dof) |
d4777acb | 466 | { |
d4777acb JM |
467 | struct gdbarch *gdbarch = get_objfile_arch (objfile); |
468 | struct dtrace_dof_sect *section; | |
469 | int i; | |
470 | ||
471 | /* The first step is to check for the DOF magic number. If no valid | |
472 | DOF data is found in the section then a complaint is issued to | |
473 | the user and the section skipped. */ | |
474 | if (dof->dofh_ident[DTRACE_DOF_ID_MAG0] != 0x7F | |
475 | || dof->dofh_ident[DTRACE_DOF_ID_MAG1] != 'D' | |
476 | || dof->dofh_ident[DTRACE_DOF_ID_MAG2] != 'O' | |
477 | || dof->dofh_ident[DTRACE_DOF_ID_MAG3] != 'F') | |
478 | goto invalid_dof_data; | |
479 | ||
480 | /* Make sure the encoding mark is either DTRACE_DOF_ENCODE_LSB or | |
481 | DTRACE_DOF_ENCODE_MSB. */ | |
482 | if (dof->dofh_ident[DTRACE_DOF_ID_ENCODING] != DTRACE_DOF_ENCODE_LSB | |
483 | && dof->dofh_ident[DTRACE_DOF_ID_ENCODING] != DTRACE_DOF_ENCODE_MSB) | |
484 | goto invalid_dof_data; | |
485 | ||
486 | /* Make sure this DOF is not an enabling DOF, i.e. there are no ECB | |
487 | Description sections. */ | |
488 | section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof, | |
489 | DOF_UINT (dof, dof->dofh_secoff)); | |
490 | for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++) | |
491 | if (section->dofs_type == DTRACE_DOF_SECT_TYPE_ECBDESC) | |
492 | return; | |
493 | ||
494 | /* Iterate over any section of type Provider and extract the probe | |
495 | information from them. If there are no "provider" sections on | |
496 | the DOF then we just return. */ | |
497 | section = (struct dtrace_dof_sect *) DTRACE_DOF_PTR (dof, | |
498 | DOF_UINT (dof, dof->dofh_secoff)); | |
499 | for (i = 0; i < DOF_UINT (dof, dof->dofh_secnum); i++, section++) | |
500 | if (DOF_UINT (dof, section->dofs_type) == DTRACE_DOF_SECT_TYPE_PROVIDER) | |
501 | { | |
502 | struct dtrace_dof_provider *provider = (struct dtrace_dof_provider *) | |
503 | DTRACE_DOF_PTR (dof, DOF_UINT (dof, section->dofs_offset)); | |
504 | struct dtrace_dof_sect *strtab_s | |
505 | = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_strtab)); | |
506 | struct dtrace_dof_sect *probes_s | |
507 | = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_probes)); | |
508 | struct dtrace_dof_sect *args_s | |
509 | = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prargs)); | |
510 | struct dtrace_dof_sect *offsets_s | |
511 | = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_proffs)); | |
512 | struct dtrace_dof_sect *eoffsets_s | |
513 | = DTRACE_DOF_SECT (dof, DOF_UINT (dof, provider->dofpv_prenoffs)); | |
514 | char *strtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, strtab_s->dofs_offset)); | |
515 | char *offtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, offsets_s->dofs_offset)); | |
516 | char *eofftab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, eoffsets_s->dofs_offset)); | |
517 | char *argtab = DTRACE_DOF_PTR (dof, DOF_UINT (dof, args_s->dofs_offset)); | |
518 | unsigned int entsize = DOF_UINT (dof, probes_s->dofs_entsize); | |
519 | int num_probes; | |
520 | ||
47e9c225 JB |
521 | if (DOF_UINT (dof, section->dofs_size) |
522 | < sizeof (struct dtrace_dof_provider)) | |
523 | { | |
524 | /* The section is smaller than expected, so do not use it. | |
525 | This has been observed on x86-solaris 10. */ | |
526 | goto invalid_dof_data; | |
527 | } | |
528 | ||
d4777acb JM |
529 | /* Very, unlikely, but could crash gdb if not handled |
530 | properly. */ | |
531 | if (entsize == 0) | |
532 | goto invalid_dof_data; | |
533 | ||
534 | num_probes = DOF_UINT (dof, probes_s->dofs_size) / entsize; | |
535 | ||
536 | for (i = 0; i < num_probes; i++) | |
537 | { | |
538 | struct dtrace_dof_probe *probe = (struct dtrace_dof_probe *) | |
539 | DTRACE_DOF_PTR (dof, DOF_UINT (dof, probes_s->dofs_offset) | |
540 | + (i * DOF_UINT (dof, probes_s->dofs_entsize))); | |
541 | ||
542 | dtrace_process_dof_probe (objfile, | |
543 | gdbarch, probesp, | |
544 | dof, probe, | |
545 | provider, strtab, offtab, eofftab, argtab, | |
546 | DOF_UINT (dof, strtab_s->dofs_size)); | |
547 | } | |
548 | } | |
549 | ||
550 | return; | |
551 | ||
552 | invalid_dof_data: | |
553 | complaint (&symfile_complaints, | |
554 | _("skipping section '%s' which does not contain valid DOF data."), | |
555 | sect->name); | |
556 | } | |
557 | ||
558 | /* Helper function to build the GDB internal expressiosn that, once | |
559 | evaluated, will calculate the values of the arguments of a given | |
560 | PROBE. */ | |
561 | ||
562 | static void | |
563 | dtrace_build_arg_exprs (struct dtrace_probe *probe, | |
564 | struct gdbarch *gdbarch) | |
565 | { | |
566 | struct parser_state pstate; | |
567 | struct dtrace_probe_arg *arg; | |
568 | int i; | |
569 | ||
570 | probe->args_expr_built = 1; | |
571 | ||
572 | /* Iterate over the arguments in the probe and build the | |
573 | corresponding GDB internal expression that will generate the | |
574 | value of the argument when executed at the PC of the probe. */ | |
575 | for (i = 0; i < probe->probe_argc; i++) | |
576 | { | |
577 | struct cleanup *back_to; | |
578 | ||
579 | arg = VEC_index (dtrace_probe_arg_s, probe->args, i); | |
580 | ||
581 | /* Initialize the expression buffer in the parser state. The | |
582 | language does not matter, since we are using our own | |
583 | parser. */ | |
584 | initialize_expout (&pstate, 10, current_language, gdbarch); | |
585 | back_to = make_cleanup (free_current_contents, &pstate.expout); | |
586 | ||
587 | /* The argument value, which is ABI dependent and casted to | |
588 | `long int'. */ | |
589 | gdbarch_dtrace_parse_probe_argument (gdbarch, &pstate, i); | |
590 | ||
591 | discard_cleanups (back_to); | |
592 | ||
593 | /* Casting to the expected type, but only if the type was | |
594 | recognized at probe load time. Otherwise the argument will | |
595 | be evaluated as the long integer passed to the probe. */ | |
596 | if (arg->type != NULL) | |
597 | { | |
598 | write_exp_elt_opcode (&pstate, UNOP_CAST); | |
599 | write_exp_elt_type (&pstate, arg->type); | |
600 | write_exp_elt_opcode (&pstate, UNOP_CAST); | |
601 | } | |
602 | ||
603 | reallocate_expout (&pstate); | |
604 | arg->expr = pstate.expout; | |
605 | prefixify_expression (arg->expr); | |
606 | } | |
607 | } | |
608 | ||
609 | /* Helper function to return the Nth argument of a given PROBE. */ | |
610 | ||
611 | static struct dtrace_probe_arg * | |
612 | dtrace_get_arg (struct dtrace_probe *probe, unsigned n, | |
613 | struct gdbarch *gdbarch) | |
614 | { | |
615 | if (!probe->args_expr_built) | |
616 | dtrace_build_arg_exprs (probe, gdbarch); | |
617 | ||
618 | return VEC_index (dtrace_probe_arg_s, probe->args, n); | |
619 | } | |
620 | ||
621 | /* Implementation of the get_probes method. */ | |
622 | ||
623 | static void | |
aaa63a31 | 624 | dtrace_get_probes (std::vector<probe *> *probesp, struct objfile *objfile) |
d4777acb JM |
625 | { |
626 | bfd *abfd = objfile->obfd; | |
627 | asection *sect = NULL; | |
628 | ||
629 | /* Do nothing in case this is a .debug file, instead of the objfile | |
630 | itself. */ | |
631 | if (objfile->separate_debug_objfile_backlink != NULL) | |
632 | return; | |
633 | ||
634 | /* Iterate over the sections in OBJFILE looking for DTrace | |
635 | information. */ | |
636 | for (sect = abfd->sections; sect != NULL; sect = sect->next) | |
637 | { | |
638 | if (elf_section_data (sect)->this_hdr.sh_type == SHT_SUNW_dof) | |
639 | { | |
ffdf88ec | 640 | bfd_byte *dof; |
d4777acb JM |
641 | |
642 | /* Read the contents of the DOF section and then process it to | |
643 | extract the information of any probe defined into it. */ | |
ffdf88ec | 644 | if (!bfd_malloc_and_get_section (abfd, sect, &dof)) |
d4777acb JM |
645 | complaint (&symfile_complaints, |
646 | _("could not obtain the contents of" | |
647 | "section '%s' in objfile `%s'."), | |
648 | sect->name, abfd->filename); | |
649 | ||
ffdf88ec SE |
650 | dtrace_process_dof (sect, objfile, probesp, |
651 | (struct dtrace_dof_hdr *) dof); | |
d4777acb JM |
652 | xfree (dof); |
653 | } | |
654 | } | |
655 | } | |
656 | ||
657 | /* Helper function to determine whether a given probe is "enabled" or | |
658 | "disabled". A disabled probe is a probe in which one or more | |
659 | enablers are disabled. */ | |
660 | ||
661 | static int | |
662 | dtrace_probe_is_enabled (struct dtrace_probe *probe) | |
663 | { | |
664 | int i; | |
665 | struct gdbarch *gdbarch = probe->p.arch; | |
666 | struct dtrace_probe_enabler *enabler; | |
667 | ||
668 | for (i = 0; | |
669 | VEC_iterate (dtrace_probe_enabler_s, probe->enablers, i, enabler); | |
670 | i++) | |
671 | if (!gdbarch_dtrace_probe_is_enabled (gdbarch, enabler->address)) | |
672 | return 0; | |
673 | ||
674 | return 1; | |
675 | } | |
676 | ||
677 | /* Implementation of the get_probe_address method. */ | |
678 | ||
679 | static CORE_ADDR | |
680 | dtrace_get_probe_address (struct probe *probe, struct objfile *objfile) | |
681 | { | |
682 | gdb_assert (probe->pops == &dtrace_probe_ops); | |
683 | return probe->address + ANOFFSET (objfile->section_offsets, | |
684 | SECT_OFF_DATA (objfile)); | |
685 | } | |
686 | ||
687 | /* Implementation of the get_probe_argument_count method. */ | |
688 | ||
689 | static unsigned | |
690 | dtrace_get_probe_argument_count (struct probe *probe_generic, | |
691 | struct frame_info *frame) | |
692 | { | |
693 | struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic; | |
694 | ||
695 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
696 | ||
697 | return dtrace_probe->probe_argc; | |
698 | } | |
699 | ||
700 | /* Implementation of the can_evaluate_probe_arguments method. */ | |
701 | ||
702 | static int | |
703 | dtrace_can_evaluate_probe_arguments (struct probe *probe_generic) | |
704 | { | |
705 | struct gdbarch *gdbarch = probe_generic->arch; | |
706 | ||
707 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
708 | return gdbarch_dtrace_parse_probe_argument_p (gdbarch); | |
709 | } | |
710 | ||
711 | /* Implementation of the evaluate_probe_argument method. */ | |
712 | ||
713 | static struct value * | |
714 | dtrace_evaluate_probe_argument (struct probe *probe_generic, unsigned n, | |
715 | struct frame_info *frame) | |
716 | { | |
717 | struct gdbarch *gdbarch = probe_generic->arch; | |
718 | struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic; | |
719 | struct dtrace_probe_arg *arg; | |
720 | int pos = 0; | |
721 | ||
722 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
723 | ||
724 | arg = dtrace_get_arg (dtrace_probe, n, gdbarch); | |
725 | return evaluate_subexp_standard (arg->type, arg->expr, &pos, EVAL_NORMAL); | |
726 | } | |
727 | ||
728 | /* Implementation of the compile_to_ax method. */ | |
729 | ||
730 | static void | |
731 | dtrace_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr, | |
732 | struct axs_value *value, unsigned n) | |
733 | { | |
734 | struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe_generic; | |
735 | struct dtrace_probe_arg *arg; | |
736 | union exp_element *pc; | |
737 | ||
738 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
739 | ||
740 | arg = dtrace_get_arg (dtrace_probe, n, expr->gdbarch); | |
741 | ||
742 | pc = arg->expr->elts; | |
743 | gen_expr (arg->expr, &pc, expr, value); | |
744 | ||
745 | require_rvalue (expr, value); | |
746 | value->type = arg->type; | |
747 | } | |
748 | ||
749 | /* Implementation of the probe_destroy method. */ | |
750 | ||
751 | static void | |
752 | dtrace_probe_destroy (struct probe *probe_generic) | |
753 | { | |
754 | struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic; | |
755 | struct dtrace_probe_arg *arg; | |
756 | int i; | |
757 | ||
758 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
759 | ||
760 | for (i = 0; VEC_iterate (dtrace_probe_arg_s, probe->args, i, arg); i++) | |
761 | { | |
762 | xfree (arg->type_str); | |
763 | xfree (arg->expr); | |
764 | } | |
765 | ||
766 | VEC_free (dtrace_probe_enabler_s, probe->enablers); | |
767 | VEC_free (dtrace_probe_arg_s, probe->args); | |
768 | } | |
769 | ||
770 | /* Implementation of the type_name method. */ | |
771 | ||
772 | static const char * | |
773 | dtrace_type_name (struct probe *probe_generic) | |
774 | { | |
775 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
776 | return "dtrace"; | |
777 | } | |
778 | ||
779 | /* Implementation of the gen_info_probes_table_header method. */ | |
780 | ||
781 | static void | |
782 | dtrace_gen_info_probes_table_header (VEC (info_probe_column_s) **heads) | |
783 | { | |
784 | info_probe_column_s dtrace_probe_column; | |
785 | ||
786 | dtrace_probe_column.field_name = "enabled"; | |
787 | dtrace_probe_column.print_name = _("Enabled"); | |
788 | ||
789 | VEC_safe_push (info_probe_column_s, *heads, &dtrace_probe_column); | |
790 | } | |
791 | ||
792 | /* Implementation of the gen_info_probes_table_values method. */ | |
793 | ||
794 | static void | |
795 | dtrace_gen_info_probes_table_values (struct probe *probe_generic, | |
796 | VEC (const_char_ptr) **ret) | |
797 | { | |
798 | struct dtrace_probe *probe = (struct dtrace_probe *) probe_generic; | |
799 | const char *val = NULL; | |
800 | ||
801 | gdb_assert (probe_generic->pops == &dtrace_probe_ops); | |
802 | ||
803 | if (VEC_empty (dtrace_probe_enabler_s, probe->enablers)) | |
804 | val = "always"; | |
805 | else if (!gdbarch_dtrace_probe_is_enabled_p (probe_generic->arch)) | |
806 | val = "unknown"; | |
807 | else if (dtrace_probe_is_enabled (probe)) | |
808 | val = "yes"; | |
809 | else | |
810 | val = "no"; | |
811 | ||
812 | VEC_safe_push (const_char_ptr, *ret, val); | |
813 | } | |
814 | ||
815 | /* Implementation of the enable_probe method. */ | |
816 | ||
817 | static void | |
818 | dtrace_enable_probe (struct probe *probe) | |
819 | { | |
820 | struct gdbarch *gdbarch = probe->arch; | |
821 | struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe; | |
822 | struct dtrace_probe_enabler *enabler; | |
823 | int i; | |
824 | ||
825 | gdb_assert (probe->pops == &dtrace_probe_ops); | |
826 | ||
827 | /* Enabling a dtrace probe implies patching the text section of the | |
828 | running process, so make sure the inferior is indeed running. */ | |
829 | if (ptid_equal (inferior_ptid, null_ptid)) | |
830 | error (_("No inferior running")); | |
831 | ||
832 | /* Fast path. */ | |
833 | if (dtrace_probe_is_enabled (dtrace_probe)) | |
834 | return; | |
835 | ||
836 | /* Iterate over all defined enabler in the given probe and enable | |
837 | them all using the corresponding gdbarch hook. */ | |
838 | ||
839 | for (i = 0; | |
840 | VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler); | |
841 | i++) | |
842 | if (gdbarch_dtrace_enable_probe_p (gdbarch)) | |
843 | gdbarch_dtrace_enable_probe (gdbarch, enabler->address); | |
844 | } | |
845 | ||
846 | ||
847 | /* Implementation of the disable_probe method. */ | |
848 | ||
849 | static void | |
850 | dtrace_disable_probe (struct probe *probe) | |
851 | { | |
852 | struct gdbarch *gdbarch = probe->arch; | |
853 | struct dtrace_probe *dtrace_probe = (struct dtrace_probe *) probe; | |
854 | struct dtrace_probe_enabler *enabler; | |
855 | int i; | |
856 | ||
857 | gdb_assert (probe->pops == &dtrace_probe_ops); | |
858 | ||
859 | /* Disabling a dtrace probe implies patching the text section of the | |
860 | running process, so make sure the inferior is indeed running. */ | |
861 | if (ptid_equal (inferior_ptid, null_ptid)) | |
862 | error (_("No inferior running")); | |
863 | ||
864 | /* Fast path. */ | |
865 | if (!dtrace_probe_is_enabled (dtrace_probe)) | |
866 | return; | |
867 | ||
868 | /* Are we trying to disable a probe that does not have any enabler | |
869 | associated? */ | |
870 | if (VEC_empty (dtrace_probe_enabler_s, dtrace_probe->enablers)) | |
871 | error (_("Probe %s:%s cannot be disabled: no enablers."), probe->provider, probe->name); | |
872 | ||
873 | /* Iterate over all defined enabler in the given probe and disable | |
874 | them all using the corresponding gdbarch hook. */ | |
875 | ||
876 | for (i = 0; | |
877 | VEC_iterate (dtrace_probe_enabler_s, dtrace_probe->enablers, i, enabler); | |
878 | i++) | |
879 | if (gdbarch_dtrace_disable_probe_p (gdbarch)) | |
880 | gdbarch_dtrace_disable_probe (gdbarch, enabler->address); | |
881 | } | |
882 | ||
883 | /* DTrace probe_ops. */ | |
884 | ||
bf36a1e7 | 885 | const struct probe_ops dtrace_probe_ops = |
d4777acb JM |
886 | { |
887 | dtrace_probe_is_linespec, | |
888 | dtrace_get_probes, | |
889 | dtrace_get_probe_address, | |
890 | dtrace_get_probe_argument_count, | |
891 | dtrace_can_evaluate_probe_arguments, | |
892 | dtrace_evaluate_probe_argument, | |
893 | dtrace_compile_to_ax, | |
894 | NULL, /* set_semaphore */ | |
895 | NULL, /* clear_semaphore */ | |
896 | dtrace_probe_destroy, | |
897 | dtrace_type_name, | |
898 | dtrace_gen_info_probes_table_header, | |
899 | dtrace_gen_info_probes_table_values, | |
900 | dtrace_enable_probe, | |
901 | dtrace_disable_probe | |
902 | }; | |
903 | ||
904 | /* Implementation of the `info probes dtrace' command. */ | |
905 | ||
906 | static void | |
8d97dc1c | 907 | info_probes_dtrace_command (const char *arg, int from_tty) |
d4777acb JM |
908 | { |
909 | info_probes_for_ops (arg, from_tty, &dtrace_probe_ops); | |
910 | } | |
911 | ||
d4777acb JM |
912 | void |
913 | _initialize_dtrace_probe (void) | |
914 | { | |
0782db84 | 915 | all_probe_ops.push_back (&dtrace_probe_ops); |
d4777acb JM |
916 | |
917 | add_cmd ("dtrace", class_info, info_probes_dtrace_command, | |
918 | _("\ | |
919 | Show information about DTrace static probes.\n\ | |
920 | Usage: info probes dtrace [PROVIDER [NAME [OBJECT]]]\n\ | |
921 | Each argument is a regular expression, used to select probes.\n\ | |
922 | PROVIDER matches probe provider names.\n\ | |
923 | NAME matches the probe names.\n\ | |
924 | OBJECT matches the executable or shared library name."), | |
925 | info_probes_cmdlist_get ()); | |
926 | } |