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