]>
Commit | Line | Data |
---|---|---|
440f755a | 1 | // C++ interface to dwfl |
82fc46ce | 2 | // Copyright (C) 2005-2019 Red Hat Inc. |
440f755a JS |
3 | // Copyright (C) 2005-2007 Intel Corporation. |
4 | // Copyright (C) 2008 James.Bottomley@HansenPartnership.com | |
5 | // | |
6 | // This file is part of systemtap, and is free software. You can | |
7 | // redistribute it and/or modify it under the terms of the GNU General | |
8 | // Public License (GPL); either version 2, or (at your option) any | |
9 | // later version. | |
10 | ||
11 | #ifndef DWFLPP_H | |
12 | #define DWFLPP_H | |
13 | ||
14 | #include "config.h" | |
15 | #include "dwarf_wrappers.h" | |
16 | #include "elaborate.h" | |
17 | #include "session.h" | |
68983551 | 18 | #include "setupdwfl.h" |
a3e980f9 | 19 | #include "stringtable.h" |
440f755a JS |
20 | |
21 | #include <cstring> | |
22 | #include <iostream> | |
23 | #include <map> | |
24 | #include <set> | |
25 | #include <string> | |
5d46f7cb | 26 | #include <unordered_map> |
7fb6e0ea | 27 | #include <unordered_set> |
440f755a JS |
28 | #include <vector> |
29 | ||
d3490604 WC |
30 | // Old elf.h doesn't know about this machine type. |
31 | #ifndef EM_AARCH64 | |
32 | #define EM_AARCH64 183 | |
33 | #endif | |
34 | ||
fb0851e6 FCE |
35 | #ifndef EM_RISCV |
36 | #define EM_RISCV 243 | |
37 | #endif | |
38 | ||
39 | ||
68dfc446 WC |
40 | #define write_uleb128(ptr,val) ({ \ |
41 | uint32_t valv = (val); \ | |
42 | do \ | |
43 | { \ | |
44 | unsigned char c = valv & 0x7f; \ | |
45 | valv >>= 7; \ | |
46 | if (valv) \ | |
47 | c |= 0x80; \ | |
48 | *(ptr)++ = c; \ | |
49 | } \ | |
50 | while (valv); \ | |
51 | }) | |
52 | ||
d3490604 | 53 | |
440f755a JS |
54 | extern "C" { |
55 | #include <elfutils/libdwfl.h> | |
27646582 | 56 | #include <regex.h> |
440f755a JS |
57 | } |
58 | ||
59 | ||
959ccfed | 60 | struct base_func_info; |
440f755a JS |
61 | struct func_info; |
62 | struct inline_instance_info; | |
63 | struct symbol_table; | |
64 | struct base_query; | |
5c378838 | 65 | struct external_function_query; |
0dbac951 | 66 | struct expression; |
440f755a | 67 | |
f01d4ffb | 68 | enum lineno_t { ABSOLUTE, RELATIVE, WILDCARD, ENUMERATED }; |
440f755a JS |
69 | enum info_status { info_unknown, info_present, info_absent }; |
70 | ||
be53d313 | 71 | // module -> cu die[] |
5d46f7cb | 72 | typedef std::unordered_map<Dwarf*, std::vector<Dwarf_Die>*> module_cu_cache_t; |
be53d313 | 73 | |
337b7c44 TT |
74 | // An instance of this type tracks whether the type units for a given |
75 | // Dwarf have been read. | |
76 | typedef std::set<Dwarf*> module_tus_read_t; | |
77 | ||
b7478964 | 78 | // typename -> die |
5d46f7cb | 79 | typedef std::unordered_map<std::string, Dwarf_Die> cu_type_cache_t; |
b7478964 JS |
80 | |
81 | // cu die -> (typename -> die) | |
5d46f7cb | 82 | typedef std::unordered_map<void*, cu_type_cache_t*> mod_cu_type_cache_t; |
b7478964 | 83 | |
54558065 | 84 | // function -> die |
5d46f7cb | 85 | typedef std::unordered_multimap<interned_string, Dwarf_Die> cu_function_cache_t; |
54558065 JS |
86 | |
87 | // cu die -> (function -> die) | |
5d46f7cb | 88 | typedef std::unordered_map<void*, cu_function_cache_t*> mod_cu_function_cache_t; |
440f755a | 89 | |
4df79aaf | 90 | // module -> (function -> die) |
5d46f7cb | 91 | typedef std::unordered_map<Dwarf*, cu_function_cache_t*> mod_function_cache_t; |
4df79aaf | 92 | |
d089f5b2 | 93 | // inline function die -> instance die[] |
5d46f7cb | 94 | typedef std::unordered_map<void*, std::vector<Dwarf_Die>*> cu_inl_function_cache_t; |
d089f5b2 | 95 | |
9da6c217 JU |
96 | // function die -> [call site die, call site function die] |
97 | typedef std::pair<Dwarf_Die, Dwarf_Die> call_site_cache_t; | |
98 | typedef std::unordered_map<void*, std::vector<call_site_cache_t>*> cu_call_sites_cache_t; | |
99 | ||
9aa8ffce | 100 | // die -> parent die |
5d46f7cb | 101 | typedef std::unordered_map<void*, Dwarf_Die> cu_die_parent_cache_t; |
9aa8ffce JS |
102 | |
103 | // cu die -> (die -> parent die) | |
5d46f7cb | 104 | typedef std::unordered_map<void*, cu_die_parent_cache_t*> mod_cu_die_parent_cache_t; |
9aa8ffce | 105 | |
79121173 JL |
106 | // Dwarf_Line[] (sorted by lineno) |
107 | typedef std::vector<Dwarf_Line*> lines_t; | |
108 | typedef std::pair<lines_t::iterator, | |
109 | lines_t::iterator> | |
110 | lines_range_t; | |
111 | ||
112 | // srcfile -> Dwarf_Line[] | |
5d46f7cb | 113 | typedef std::unordered_map<std::string, lines_t*> srcfile_lines_cache_t; |
79121173 JL |
114 | |
115 | // cu die -> (srcfile -> Dwarf_Line[]) | |
5d46f7cb | 116 | typedef std::unordered_map<void*, srcfile_lines_cache_t*> cu_lines_cache_t; |
79121173 | 117 | |
7fb6e0ea JS |
118 | // cu die -> {entry pcs} |
119 | typedef std::unordered_set<Dwarf_Addr> entry_pc_cache_t; | |
120 | typedef std::unordered_map<void*, entry_pc_cache_t*> cu_entry_pc_cache_t; | |
121 | ||
959ccfed | 122 | typedef std::vector<base_func_info> base_func_info_map_t; |
440f755a JS |
123 | typedef std::vector<func_info> func_info_map_t; |
124 | typedef std::vector<inline_instance_info> inline_instance_map_t; | |
125 | ||
126 | ||
440f755a JS |
127 | struct |
128 | module_info | |
129 | { | |
130 | Dwfl_Module* mod; | |
131 | const char* name; | |
132 | std::string elf_path; | |
133 | Dwarf_Addr addr; | |
134 | Dwarf_Addr bias; | |
135 | symbol_table *sym_table; | |
136 | info_status dwarf_status; // module has dwarf info? | |
137 | info_status symtab_status; // symbol table cached? | |
138 | ||
47d349b1 FCE |
139 | std::set<interned_string> inlined_funcs; |
140 | std::set<interned_string> plt_funcs; | |
e90006d7 | 141 | std::set<std::pair<std::string,std::string> > marks; /* <provider,name> */ |
6059d7c4 | 142 | |
5f52fafe | 143 | void get_symtab(); |
1c6b77e5 | 144 | void update_symtab(cu_function_cache_t *funcs); |
440f755a JS |
145 | |
146 | module_info(const char *name) : | |
147 | mod(NULL), | |
148 | name(name), | |
149 | addr(0), | |
150 | bias(0), | |
151 | sym_table(NULL), | |
152 | dwarf_status(info_unknown), | |
153 | symtab_status(info_unknown) | |
154 | {} | |
155 | ||
156 | ~module_info(); | |
157 | }; | |
158 | ||
159 | ||
160 | struct | |
161 | module_cache | |
162 | { | |
163 | std::map<std::string, module_info*> cache; | |
164 | bool paths_collected; | |
165 | bool dwarf_collected; | |
166 | ||
167 | module_cache() : paths_collected(false), dwarf_collected(false) {} | |
435f53a7 | 168 | ~module_cache(); |
440f755a JS |
169 | }; |
170 | ||
171 | ||
e772a6e7 | 172 | struct base_func_info |
440f755a | 173 | { |
e772a6e7 | 174 | base_func_info() |
a3e980f9 | 175 | : decl_line(-1), entrypc(0) |
440f755a JS |
176 | { |
177 | std::memset(&die, 0, sizeof(die)); | |
178 | } | |
47d349b1 FCE |
179 | interned_string name; |
180 | interned_string decl_file; | |
440f755a JS |
181 | int decl_line; |
182 | Dwarf_Die die; | |
440f755a | 183 | Dwarf_Addr entrypc; |
e772a6e7 JL |
184 | }; |
185 | ||
186 | struct func_info : base_func_info | |
187 | { | |
188 | func_info() | |
189 | : addr(0), prologue_end(0), weak(false), descriptor(false) {} | |
190 | Dwarf_Addr addr; | |
440f755a | 191 | Dwarf_Addr prologue_end; |
2867a2a1 | 192 | bool weak, descriptor; |
440f755a JS |
193 | }; |
194 | ||
195 | ||
e772a6e7 | 196 | struct inline_instance_info : base_func_info |
440f755a | 197 | { |
e772a6e7 | 198 | inline_instance_info() {} |
7fdd3e2c | 199 | bool operator<(const inline_instance_info& other) const; |
440f755a JS |
200 | }; |
201 | ||
0dbac951 | 202 | struct location; |
439fb4cc | 203 | class location_context; |
440f755a JS |
204 | |
205 | struct dwflpp | |
206 | { | |
207 | systemtap_session & sess; | |
440f755a JS |
208 | |
209 | // These are "current" values we focus on. | |
210 | Dwfl_Module * module; | |
440f755a JS |
211 | Dwarf_Addr module_bias; |
212 | module_info * mod_info; | |
213 | ||
214 | // These describe the current module's PC address range | |
215 | Dwarf_Addr module_start; | |
216 | Dwarf_Addr module_end; | |
217 | ||
218 | Dwarf_Die * cu; | |
440f755a JS |
219 | |
220 | std::string module_name; | |
440f755a JS |
221 | std::string function_name; |
222 | ||
747902ed | 223 | dwflpp(systemtap_session & session, const std::string& user_module, bool kernel_p, bool debuginfo_needed = true); |
59c11f91 | 224 | dwflpp(systemtap_session & session, const std::vector<std::string>& user_modules, bool kernel_p); |
440f755a JS |
225 | ~dwflpp(); |
226 | ||
440f755a JS |
227 | void get_module_dwarf(bool required = false, bool report = true); |
228 | ||
229 | void focus_on_module(Dwfl_Module * m, module_info * mi); | |
230 | void focus_on_cu(Dwarf_Die * c); | |
231 | void focus_on_function(Dwarf_Die * f); | |
440f755a | 232 | |
54417494 JS |
233 | std::string cu_name(void); |
234 | ||
1adf8ef1 | 235 | Dwarf_Die *query_cu_containing_address(Dwarf_Addr a); |
440f755a | 236 | |
5f4c8c6e | 237 | bool module_name_matches(const std::string& pattern); |
665e1256 | 238 | static bool name_has_wildcard(const std::string& pattern); |
5f4c8c6e | 239 | bool module_name_final_match(const std::string& pattern); |
440f755a | 240 | |
5f4c8c6e JS |
241 | bool function_name_matches_pattern(const std::string& name, const std::string& pattern); |
242 | bool function_name_matches(const std::string& pattern); | |
c646240d | 243 | bool function_scope_matches(const std::vector<std::string>& scopes); |
440f755a | 244 | |
06de3a04 JL |
245 | template<typename T> |
246 | void iterate_over_modules(int (* callback)(Dwfl_Module*, | |
247 | void**, | |
248 | const char*, | |
249 | Dwarf_Addr, | |
250 | T*), | |
251 | T *data) | |
252 | { | |
253 | /* We're using templates here to enforce type-safety between the data arg | |
254 | * we're requested to pass to callback, and the data arg that the callback | |
255 | * actually takes. Rather than putting the implementation here, we simply | |
256 | * call the <void> specialization, which does the real work. | |
257 | * As a result, we need to cast the data arg in the callback signature | |
258 | * and the one passed to void* (which is what elfutils also works with). | |
259 | * */ | |
260 | iterate_over_modules<void>((int (*)(Dwfl_Module*, | |
261 | void**, | |
262 | const char*, | |
263 | Dwarf_Addr, | |
264 | void *))callback, | |
265 | (void*)data); | |
266 | } | |
440f755a | 267 | |
5c378838 JL |
268 | template<typename T> |
269 | void iterate_over_cus(int (* callback)(Dwarf_Die*, T*), | |
270 | T *data, | |
271 | bool want_types) | |
272 | { | |
273 | // See comment block in iterate_over_modules() | |
274 | iterate_over_cus<void>((int (*)(Dwarf_Die*, void*))callback, | |
275 | (void*)data, | |
276 | want_types); | |
277 | } | |
440f755a JS |
278 | |
279 | bool func_is_inline(); | |
280 | ||
4bda987e SC |
281 | bool func_is_exported(); |
282 | ||
3956fccb JL |
283 | template<typename T> |
284 | void iterate_over_inline_instances(int (* callback)(Dwarf_Die*, T*), | |
285 | T *data) | |
286 | { | |
287 | // See comment block in iterate_over_modules() | |
288 | iterate_over_inline_instances<void>((int (*)(Dwarf_Die*, void*))callback, | |
289 | (void*)data); | |
290 | } | |
440f755a | 291 | |
9da6c217 JU |
292 | template<typename T> |
293 | void iterate_over_call_sites(int (* callback)(Dwarf_Die*, Dwarf_Die*, T*), | |
294 | T *data) | |
295 | { | |
296 | // See comment block in iterate_over_modules() | |
297 | iterate_over_call_sites<void>((int (*)(Dwarf_Die*, Dwarf_Die*, void*))callback, | |
298 | (void*)data); | |
299 | } | |
300 | ||
9aa8ffce | 301 | std::vector<Dwarf_Die> getscopes_die(Dwarf_Die* die); |
729455a7 JS |
302 | std::vector<Dwarf_Die> getscopes(Dwarf_Die* die); |
303 | std::vector<Dwarf_Die> getscopes(Dwarf_Addr pc); | |
9aa8ffce | 304 | |
a44a7cb5 JS |
305 | Dwarf_Die *declaration_resolve(Dwarf_Die *type); |
306 | Dwarf_Die *declaration_resolve(const std::string& name); | |
307 | Dwarf_Die *declaration_resolve_other_cus(const std::string& name); | |
440f755a | 308 | |
7d007451 JL |
309 | template<typename T> |
310 | int iterate_over_functions (int (* callback)(Dwarf_Die*, T*), | |
311 | T *data, const std::string& function) | |
312 | { | |
313 | // See comment block in iterate_over_modules() | |
314 | return iterate_over_functions<void>((int (*)(Dwarf_Die*, void*))callback, | |
315 | (void*)data, function); | |
316 | } | |
440f755a | 317 | |
7d007451 JL |
318 | template<typename T> |
319 | int iterate_single_function (int (* callback)(Dwarf_Die*, T*), | |
320 | T *data, const std::string& function) | |
321 | { | |
322 | // See comment block in iterate_over_modules() | |
323 | return iterate_single_function<void>((int (*)(Dwarf_Die*, void*))callback, | |
324 | (void*)data, function); | |
325 | } | |
4df79aaf | 326 | |
488d3c1b JL |
327 | template<typename T> |
328 | int iterate_over_notes (T *object, | |
dbd24034 JL |
329 | void (* callback)(T*, const std::string&, |
330 | const std::string&, | |
331 | int, const char*, size_t)) | |
488d3c1b JL |
332 | { |
333 | // See comment block in iterate_over_modules() | |
334 | return iterate_over_notes<void>((void*)object, | |
335 | (void (*)(void*, | |
dbd24034 JL |
336 | const std::string&, |
337 | const std::string&, | |
488d3c1b JL |
338 | int, |
339 | const char*, | |
340 | size_t))callback); | |
341 | } | |
342 | ||
bbbc7241 JL |
343 | template<typename T> |
344 | void iterate_over_libraries (void (*callback)(T*, const char*), T *data) | |
345 | { | |
346 | // See comment block in iterate_over_modules() | |
347 | iterate_over_libraries<void>((void (*)(void*, | |
348 | const char*))callback, | |
349 | (void*)data); | |
350 | } | |
351 | ||
45cdb40e JL |
352 | template<typename T> |
353 | int iterate_over_plt (T *object, void (*callback)(T*, const char*, size_t)) | |
354 | { | |
355 | // See comment block in iterate_over_modules() | |
356 | return iterate_over_plt<void>((void*)object, | |
357 | (void (*)(void*, | |
358 | const char*, | |
359 | size_t))callback); | |
360 | } | |
bbbc7241 | 361 | |
0e2e28a1 | 362 | template<typename T> |
440f755a | 363 | void iterate_over_srcfile_lines (char const * srcfile, |
10e6fe03 | 364 | const std::vector<int>& linenos, |
4a81c0d9 | 365 | enum lineno_t lineno_type, |
516e1e2c | 366 | base_func_info_map_t& funcs, |
de797211 JL |
367 | void (*callback) (Dwarf_Addr, |
368 | int, T*), | |
83eeb3ac | 369 | bool has_nearest, |
0e2e28a1 JL |
370 | T *data) |
371 | { | |
372 | // See comment block in iterate_over_modules() | |
373 | iterate_over_srcfile_lines<void>(srcfile, | |
4a81c0d9 | 374 | linenos, |
4a81c0d9 | 375 | lineno_type, |
516e1e2c | 376 | funcs, |
de797211 JL |
377 | (void (*)(Dwarf_Addr, |
378 | int, void*))callback, | |
83eeb3ac | 379 | has_nearest, |
0e2e28a1 JL |
380 | (void*)data); |
381 | } | |
440f755a | 382 | |
147a2577 | 383 | template<typename T> |
440f755a | 384 | void iterate_over_labels (Dwarf_Die *begin_die, |
8096dd7d | 385 | const std::string& sym, |
600d39f1 | 386 | const base_func_info& function, |
10e6fe03 | 387 | const std::vector<int>& linenos, |
600d39f1 | 388 | enum lineno_t lineno_type, |
147a2577 | 389 | T *data, |
600d39f1 | 390 | void (* callback)(const base_func_info&, |
147a2577 JL |
391 | const char*, |
392 | const char*, | |
440f755a | 393 | int, |
147a2577 | 394 | Dwarf_Die*, |
440f755a | 395 | Dwarf_Addr, |
147a2577 JL |
396 | T*)) |
397 | { | |
398 | // See comment block in iterate_over_modules() | |
399 | iterate_over_labels<void>(begin_die, | |
400 | sym, | |
401 | function, | |
600d39f1 JL |
402 | linenos, |
403 | lineno_type, | |
147a2577 | 404 | (void*)data, |
600d39f1 | 405 | (void (*)(const base_func_info&, |
147a2577 JL |
406 | const char*, |
407 | const char*, | |
408 | int, | |
409 | Dwarf_Die*, | |
410 | Dwarf_Addr, | |
411 | void*))callback); | |
412 | } | |
440f755a | 413 | |
172688cb | 414 | template<typename T> |
67959c62 JL |
415 | void iterate_over_callees (Dwarf_Die *begin_die, |
416 | const std::string& sym, | |
b3fbdd3e | 417 | int64_t recursion_depth, |
172688cb | 418 | T *data, |
e772a6e7 JL |
419 | void (* callback)(base_func_info&, |
420 | base_func_info&, | |
67959c62 | 421 | std::stack<Dwarf_Addr>*, |
172688cb | 422 | T*), |
e772a6e7 | 423 | base_func_info& caller, |
919debfc | 424 | std::stack<Dwarf_Addr>*callers=NULL) |
172688cb JL |
425 | { |
426 | // See comment block in iterate_over_modules() | |
427 | iterate_over_callees<void>(begin_die, | |
428 | sym, | |
429 | recursion_depth, | |
430 | (void*)data, | |
e772a6e7 JL |
431 | (void (*)(base_func_info&, |
432 | base_func_info&, | |
172688cb JL |
433 | std::stack<Dwarf_Addr>*, |
434 | void*))callback, | |
e772a6e7 | 435 | caller, |
919debfc | 436 | callers); |
172688cb | 437 | } |
67959c62 | 438 | |
16b2359a AM |
439 | template<typename T> |
440 | static int iterate_over_globals (Dwarf_Die *cu_die, | |
441 | int (* callback)(Dwarf_Die*, | |
442 | bool, | |
443 | const std::string&, | |
444 | T*), | |
445 | T *data) | |
446 | { | |
447 | // See comment block in iterate_over_modules() | |
448 | return iterate_over_globals<void>(cu_die, | |
449 | (int (*)(Dwarf_Die*, | |
450 | bool, | |
451 | const std::string&, | |
452 | void*))callback, | |
453 | (void*)data); | |
454 | } | |
455 | ||
448a86b7 JS |
456 | GElf_Shdr * get_section(std::string section_name, GElf_Shdr *shdr_mem, |
457 | Elf **elf_ret=NULL); | |
fea74777 | 458 | |
440f755a | 459 | void collect_srcfiles_matching (std::string const & pattern, |
bd25380d | 460 | std::set<std::string> & filtered_srcfiles); |
440f755a JS |
461 | |
462 | void resolve_prologue_endings (func_info_map_t & funcs); | |
463 | ||
1bbf3f90 JS |
464 | bool function_entrypc (Dwarf_Addr * addr) __attribute__((warn_unused_result)); |
465 | bool die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr) __attribute__((warn_unused_result)); | |
440f755a JS |
466 | |
467 | void function_die (Dwarf_Die *d); | |
468 | void function_file (char const ** c); | |
469 | void function_line (int *linep); | |
470 | ||
471 | bool die_has_pc (Dwarf_Die & die, Dwarf_Addr pc); | |
2a43d5db | 472 | bool inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr, |
f5958c8f | 473 | Dwarf_Die& result); |
440f755a | 474 | |
0dbac951 RH |
475 | bool literal_stmt_for_local (location_context &ctx, |
476 | std::vector<Dwarf_Die>& scopes, | |
477 | std::string const & local, | |
478 | const target_symbol *e, | |
479 | bool lvalue, | |
480 | Dwarf_Die *die_mem); | |
5f36109e | 481 | Dwarf_Die* type_die_for_local (std::vector<Dwarf_Die>& scopes, |
0dbac951 | 482 | Dwarf_Addr pc, |
5f36109e JS |
483 | std::string const & local, |
484 | const target_symbol *e, | |
9c141eca DS |
485 | Dwarf_Die *die_mem, |
486 | bool lvalue); | |
d0b4a5ff | 487 | |
0dbac951 RH |
488 | bool literal_stmt_for_return (location_context &ctx, |
489 | Dwarf_Die *scope_die, | |
490 | const target_symbol *e, | |
491 | bool lvalue, | |
492 | Dwarf_Die *die_mem); | |
5f36109e JS |
493 | Dwarf_Die* type_die_for_return (Dwarf_Die *scope_die, |
494 | Dwarf_Addr pc, | |
495 | const target_symbol *e, | |
9c141eca DS |
496 | Dwarf_Die *die_mem, |
497 | bool lvalue); | |
d0b4a5ff | 498 | |
0dbac951 RH |
499 | bool literal_stmt_for_pointer (location_context &ctx, |
500 | Dwarf_Die *type_die, | |
501 | const target_symbol *e, | |
502 | bool lvalue, | |
503 | Dwarf_Die *die_mem); | |
5f36109e JS |
504 | Dwarf_Die* type_die_for_pointer (Dwarf_Die *type_die, |
505 | const target_symbol *e, | |
9c141eca DS |
506 | Dwarf_Die *die_mem, |
507 | bool lvalue); | |
d0b4a5ff | 508 | |
d1804e05 AZ |
509 | enum blocklisted_type |
510 | { blocklisted_none, // not blocklisted | |
511 | blocklisted_section, | |
512 | blocklisted_kprobes, | |
513 | blocklisted_function, | |
514 | blocklisted_function_return, | |
515 | blocklisted_file | |
2f18e69b JL |
516 | }; |
517 | ||
d1804e05 | 518 | blocklisted_type blocklisted_p(interned_string funcname, |
45a63356 | 519 | interned_string filename, |
2f18e69b | 520 | int line, |
45a63356 | 521 | interned_string module, |
2f18e69b JL |
522 | Dwarf_Addr addr, |
523 | bool has_return); | |
27646582 | 524 | |
45a63356 | 525 | Dwarf_Addr relocate_address(Dwarf_Addr addr, interned_string& reloc_section); |
27646582 | 526 | |
5f36109e JS |
527 | void resolve_unqualified_inner_typedie (Dwarf_Die *typedie, |
528 | Dwarf_Die *innerdie, | |
529 | const target_symbol *e); | |
530 | ||
c5810d31 | 531 | bool has_gnu_debugdata(); |
277a2b96 | 532 | bool has_valid_locs(); |
27646582 | 533 | |
9da6c217 JU |
534 | location *translate_call_site_value (location_context *ctx, |
535 | Dwarf_Attribute *attr, | |
536 | Dwarf_Die *die, | |
537 | Dwarf_Die *funcdie, | |
538 | Dwarf_Addr pc); | |
539 | ||
d0b4a5ff | 540 | private: |
ccf2c922 | 541 | Dwfl * dwfl; |
d0b4a5ff JS |
542 | |
543 | // These are "current" values we focus on. | |
544 | Dwarf * module_dwarf; | |
545 | Dwarf_Die * function; | |
546 | ||
2eb99c62 | 547 | void setup_kernel(const std::string& module_name, systemtap_session &s, bool debuginfo_needed = true); |
59c11f91 | 548 | void setup_kernel(const std::vector<std::string>& modules, bool debuginfo_needed = true); |
0c16d512 | 549 | void setup_user(const std::vector<std::string>& modules, bool debuginfo_needed = true); |
d0b4a5ff | 550 | |
d0b4a5ff | 551 | module_cu_cache_t module_cu_cache; |
337b7c44 | 552 | module_tus_read_t module_tus_read; |
4df79aaf JS |
553 | mod_cu_function_cache_t cu_function_cache; |
554 | mod_function_cache_t mod_function_cache; | |
d0b4a5ff | 555 | |
8d7a7bd9 | 556 | std::set<void*> cu_inl_function_cache_done; // CUs that are already cached |
d0b4a5ff | 557 | cu_inl_function_cache_t cu_inl_function_cache; |
8d7a7bd9 | 558 | void cache_inline_instances (Dwarf_Die* die); |
d0b4a5ff | 559 | |
9da6c217 JU |
560 | std::set<void*> cu_call_sites_cache_done; // CUs that are already cached |
561 | cu_call_sites_cache_t cu_call_sites_cache; | |
562 | void cache_call_sites (Dwarf_Die* die, Dwarf_Die *function); | |
563 | ||
9aa8ffce JS |
564 | mod_cu_die_parent_cache_t cu_die_parent_cache; |
565 | void cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die); | |
729455a7 | 566 | cu_die_parent_cache_t *get_die_parents(); |
9aa8ffce | 567 | |
79121173 JL |
568 | // Cache for cu lines sorted by lineno |
569 | cu_lines_cache_t cu_lines_cache; | |
570 | ||
7fb6e0ea JS |
571 | // Cache for all entry_pc in each cu |
572 | cu_entry_pc_cache_t cu_entry_pc_cache; | |
573 | bool check_cu_entry_pc(Dwarf_Die *cu, Dwarf_Addr pc); | |
574 | ||
7d6d0afc JS |
575 | Dwarf_Die* get_parent_scope(Dwarf_Die* die); |
576 | ||
d0b4a5ff JS |
577 | /* The global alias cache is used to resolve any DIE found in a |
578 | * module that is stubbed out with DW_AT_declaration with a defining | |
579 | * DIE found in a different module. The current assumption is that | |
580 | * this only applies to structures and unions, which have a global | |
581 | * namespace (it deliberately only traverses program scope), so this | |
582 | * cache is indexed by name. If other declaration lookups were | |
583 | * added to it, it would have to be indexed by name and tag | |
584 | */ | |
b7478964 | 585 | mod_cu_type_cache_t global_alias_cache; |
3805a31e | 586 | static int global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types, |
bf072c60 | 587 | const std::string& prefix, cu_type_cache_t *cache); |
5c378838 | 588 | static int global_alias_caching_callback_cus(Dwarf_Die *die, dwflpp *dw); |
06de3a04 | 589 | |
bf072c60 JL |
590 | template<typename T> |
591 | static int iterate_over_types (Dwarf_Die *top_die, | |
592 | bool has_inner_types, | |
593 | const std::string& prefix, | |
594 | int (* callback)(Dwarf_Die*, | |
595 | bool, | |
596 | const std::string&, | |
597 | T*), | |
598 | T *data) | |
599 | { | |
600 | // See comment block in iterate_over_modules() | |
601 | return iterate_over_types<void>(top_die, has_inner_types, prefix, | |
602 | (int (*)(Dwarf_Die*, | |
603 | bool, | |
604 | const std::string&, | |
605 | void*))callback, | |
606 | (void*)data); | |
607 | } | |
d0b4a5ff | 608 | |
5c378838 JL |
609 | static int mod_function_caching_callback (Dwarf_Die* func, cu_function_cache_t *v); |
610 | static int cu_function_caching_callback (Dwarf_Die* func, cu_function_cache_t *v); | |
79121173 JL |
611 | |
612 | lines_t* get_cu_lines_sorted_by_lineno(const char *srcfile); | |
613 | ||
516e1e2c JL |
614 | void collect_lines_for_single_lineno(char const * srcfile, |
615 | int lineno, | |
616 | bool is_relative, | |
617 | base_func_info_map_t& funcs, | |
618 | lines_t& matching_lines); | |
619 | void collect_all_lines(char const * srcfile, | |
620 | base_func_info_map_t& funcs, | |
621 | lines_t& matching_lines); | |
2bc35ff7 JL |
622 | std::pair<int,int> get_nearest_linenos(char const * srcfile, |
623 | int lineno, | |
624 | base_func_info_map_t& funcs); | |
625 | int get_nearest_lineno(char const * srcfile, | |
626 | int lineno, | |
627 | base_func_info_map_t& funcs); | |
8eaab3fd JL |
628 | void suggest_alternative_linenos(char const * srcfile, |
629 | int lineno, | |
630 | base_func_info_map_t& funcs); | |
516e1e2c | 631 | |
5c378838 | 632 | static int external_function_cu_callback (Dwarf_Die* cu, external_function_query *efq); |
7d007451 | 633 | static int external_function_func_callback (Dwarf_Die* func, external_function_query *efq); |
d0b4a5ff | 634 | |
15553cab | 635 | static void loc2c_error (void *, const char *fmt, ...) __attribute__ ((noreturn)); |
440f755a JS |
636 | |
637 | // This function generates code used for addressing computations of | |
638 | // target variables. | |
0dbac951 | 639 | void emit_address (Dwarf_Addr address); |
440f755a | 640 | |
1ef2edcd | 641 | int dwarf_get_enum (Dwarf_Die *scopes, int nscopes, |
27115ab4 | 642 | const char *name, Dwarf_Die *result, Dwarf_Die *type); |
2b4f27bd JL |
643 | void get_locals(std::vector<Dwarf_Die>& scopes, std::set<std::string>& locals); |
644 | void get_locals_die(Dwarf_Die &die, std::set<std::string>& locals); | |
f5f03f5d | 645 | void get_members(Dwarf_Die *vardie, std::set<std::string>& members, |
1de6dd7a | 646 | std::set<std::string> &dupes); |
440f755a | 647 | |
729455a7 | 648 | Dwarf_Attribute *find_variable_and_frame_base (std::vector<Dwarf_Die>& scopes, |
440f755a JS |
649 | Dwarf_Addr pc, |
650 | std::string const & local, | |
651 | const target_symbol *e, | |
652 | Dwarf_Die *vardie, | |
27115ab4 | 653 | Dwarf_Die *typedie, |
9da6c217 JU |
654 | Dwarf_Attribute *fb_attr_mem, |
655 | Dwarf_Die *funcdie); | |
440f755a | 656 | |
dabd71bb MW |
657 | std::string die_location_as_string(Dwarf_Die*); |
658 | std::string pc_location_as_function_string(Dwarf_Addr); | |
6fcc2aa1 MW |
659 | std::string pc_die_line_string(Dwarf_Addr, Dwarf_Die*); |
660 | ||
151be4bd MW |
661 | /* source file name, line and column info for pc in current cu. */ |
662 | const char *pc_line (Dwarf_Addr, int *, int *); | |
663 | ||
0dbac951 RH |
664 | location *translate_location(location_context *ctx, |
665 | Dwarf_Attribute *attr, | |
666 | Dwarf_Die *die, | |
667 | Dwarf_Addr pc, | |
668 | Dwarf_Attribute *fb_attr, | |
669 | const target_symbol *e, | |
670 | location *input); | |
440f755a | 671 | |
c67847a0 | 672 | bool find_struct_member(const target_symbol::component& c, |
440f755a | 673 | Dwarf_Die *parentdie, |
440f755a | 674 | Dwarf_Die *memberdie, |
00730da1 | 675 | std::vector<Dwarf_Die>& dies, |
440f755a JS |
676 | std::vector<Dwarf_Attribute>& locs); |
677 | ||
0dbac951 RH |
678 | void translate_components(location_context *ctx, |
679 | Dwarf_Addr pc, | |
6ce303b8 JS |
680 | const target_symbol *e, |
681 | Dwarf_Die *vardie, | |
f3b5366d | 682 | Dwarf_Die *typedie, |
9c141eca | 683 | bool lvalue, |
f3b5366d | 684 | unsigned first=0); |
6ce303b8 | 685 | |
b4e7ba40 RH |
686 | void translate_base_ref (location_context &ctx, Dwarf_Word byte_size, |
687 | bool signed_p, bool lvalue_p); | |
e870b754 | 688 | void translate_bitfield(location_context &ctx, Dwarf_Word byte_size, |
aeb35e50 FCE |
689 | Dwarf_Word bit_offset, Dwarf_Word bit_size, |
690 | bool signed_p); | |
0dbac951 RH |
691 | void translate_final_fetch_or_store (location_context &ctx, |
692 | Dwarf_Die *vardie, | |
693 | Dwarf_Die *typedie, | |
694 | bool lvalue, | |
695 | Dwarf_Die *enddie); | |
9c141eca DS |
696 | void translate_pointer(location_context &ctx, Dwarf_Die *typedie, |
697 | bool lvalue); | |
27646582 | 698 | |
d1804e05 AZ |
699 | regex_t blocklist_func; // function/statement probes |
700 | regex_t blocklist_func_ret; // only for .return probes | |
701 | regex_t blocklist_file; // file name | |
702 | regex_t blocklist_section; // init/exit sections | |
703 | bool blocklist_enabled; | |
704 | void build_kernel_blocklist(); | |
705 | void build_user_blocklist(); | |
706 | std::string get_blocklist_section(Dwarf_Addr addr); | |
c8ad0687 | 707 | |
00b01a99 MW |
708 | // Returns the call frame address operations for the given program counter. |
709 | Dwarf_Op *get_cfa_ops (Dwarf_Addr pc); | |
710 | ||
228af5c4 | 711 | Dwarf_Addr vardie_from_symtable(Dwarf_Die *vardie, Dwarf_Addr *addr); |
2eb99c62 CM |
712 | |
713 | static int add_module_build_id_to_hash (Dwfl_Module *m, | |
714 | void **userdata __attribute__ ((unused)), | |
715 | const char *name, | |
716 | Dwarf_Addr base, | |
717 | void *arg); | |
718 | ||
7d31f657 JL |
719 | static bool is_gcc_producer(Dwarf_Die *cudie, std::string& producer, |
720 | std::string& version); | |
721 | ||
45b02a36 FCE |
722 | public: |
723 | Dwarf_Addr pr15123_retry_addr (Dwarf_Addr pc, Dwarf_Die* var); | |
440f755a JS |
724 | }; |
725 | ||
3956fccb JL |
726 | // Template <void> specializations for iterate_over_* functions |
727 | ||
06de3a04 JL |
728 | template<> void |
729 | dwflpp::iterate_over_modules<void>(int (*callback)(Dwfl_Module*, | |
730 | void**, | |
731 | const char*, | |
732 | Dwarf_Addr, | |
733 | void*), | |
734 | void *data); | |
5c378838 JL |
735 | template<> void |
736 | dwflpp::iterate_over_cus<void>(int (*callback)(Dwarf_Die*, void*), | |
737 | void *data, | |
738 | bool want_types); | |
3956fccb JL |
739 | template<> void |
740 | dwflpp::iterate_over_inline_instances<void>(int (*callback)(Dwarf_Die*, void*), | |
741 | void *data); | |
9da6c217 JU |
742 | template<> void |
743 | dwflpp::iterate_over_call_sites<void>(int (*callback)(Dwarf_Die*, Dwarf_Die*, void*), | |
744 | void *data); | |
7d007451 JL |
745 | template<> int |
746 | dwflpp::iterate_over_functions<void>(int (*callback)(Dwarf_Die*, void*), | |
747 | void *data, const std::string& function); | |
748 | template<> int | |
749 | dwflpp::iterate_single_function<void>(int (*callback)(Dwarf_Die*, void*), | |
750 | void *data, const std::string& function); | |
bf072c60 JL |
751 | template<> int |
752 | dwflpp::iterate_over_globals<void>(Dwarf_Die *cu_die, | |
753 | int (*callback)(Dwarf_Die*, | |
754 | bool, | |
755 | const std::string&, | |
756 | void*), | |
757 | void *data); | |
758 | template<> int | |
759 | dwflpp::iterate_over_types<void>(Dwarf_Die *top_die, | |
760 | bool has_inner_types, | |
761 | const std::string& prefix, | |
762 | int (* callback)(Dwarf_Die*, | |
763 | bool, | |
764 | const std::string&, | |
765 | void*), | |
766 | void *data); | |
488d3c1b JL |
767 | template<> int |
768 | dwflpp::iterate_over_notes<void>(void *object, void (*callback)(void*, | |
dbd24034 JL |
769 | const std::string&, |
770 | const std::string&, | |
488d3c1b JL |
771 | int, |
772 | const char*, | |
773 | size_t)); | |
bbbc7241 JL |
774 | template<> void |
775 | dwflpp::iterate_over_libraries<void>(void (*callback)(void*, const char*), | |
776 | void *data); | |
45cdb40e JL |
777 | template<> int |
778 | dwflpp::iterate_over_plt<void>(void *object, void (*callback)(void*, | |
779 | const char*, | |
780 | size_t)); | |
0e2e28a1 JL |
781 | template<> void |
782 | dwflpp::iterate_over_srcfile_lines<void>(char const * srcfile, | |
10e6fe03 | 783 | const std::vector<int>& linenos, |
4a81c0d9 | 784 | enum lineno_t lineno_type, |
516e1e2c | 785 | base_func_info_map_t& funcs, |
de797211 JL |
786 | void (* callback) (Dwarf_Addr, |
787 | int, void*), | |
83eeb3ac | 788 | bool has_nearest, |
0e2e28a1 | 789 | void *data); |
147a2577 JL |
790 | template<> void |
791 | dwflpp::iterate_over_labels<void>(Dwarf_Die *begin_die, | |
792 | const std::string& sym, | |
600d39f1 | 793 | const base_func_info& function, |
10e6fe03 | 794 | const std::vector<int>& linenos, |
600d39f1 | 795 | enum lineno_t lineno_type, |
147a2577 | 796 | void *data, |
600d39f1 | 797 | void (* callback)(const base_func_info&, |
147a2577 JL |
798 | const char*, |
799 | const char*, | |
800 | int, | |
801 | Dwarf_Die*, | |
802 | Dwarf_Addr, | |
803 | void*)); | |
172688cb JL |
804 | template<> void |
805 | dwflpp::iterate_over_callees<void>(Dwarf_Die *begin_die, | |
806 | const std::string& sym, | |
b3fbdd3e | 807 | int64_t recursion_depth, |
172688cb | 808 | void *data, |
e772a6e7 JL |
809 | void (* callback)(base_func_info&, |
810 | base_func_info&, | |
172688cb JL |
811 | std::stack<Dwarf_Addr>*, |
812 | void*), | |
e772a6e7 | 813 | base_func_info& caller, |
919debfc | 814 | std::stack<Dwarf_Addr> *callers); |
06de3a04 | 815 | |
440f755a JS |
816 | #endif // DWFLPP_H |
817 | ||
818 | /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |