Branch data Line data Source code
1 : : // C++ interface to dwfl
2 : : // Copyright (C) 2005-2013 Red Hat Inc.
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"
18 : : #include "unordered.h"
19 : : #include "setupdwfl.h"
20 : :
21 : : #include <cstring>
22 : : #include <iostream>
23 : : #include <map>
24 : : #include <set>
25 : : #include <string>
26 : : #include <vector>
27 : :
28 : : extern "C" {
29 : : #include <elfutils/libdwfl.h>
30 : : #include <regex.h>
31 : : }
32 : :
33 : :
34 : : struct func_info;
35 : : struct inline_instance_info;
36 : : struct symbol_table;
37 : : struct base_query;
38 : : struct dwarf_query;
39 : :
40 : : enum line_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD };
41 : : enum info_status { info_unknown, info_present, info_absent };
42 : :
43 : : // module -> cu die[]
44 : : typedef unordered_map<Dwarf*, std::vector<Dwarf_Die>*> module_cu_cache_t;
45 : :
46 : : // An instance of this type tracks whether the type units for a given
47 : : // Dwarf have been read.
48 : : typedef std::set<Dwarf*> module_tus_read_t;
49 : :
50 : : // typename -> die
51 : : typedef unordered_map<std::string, Dwarf_Die> cu_type_cache_t;
52 : :
53 : : // cu die -> (typename -> die)
54 : : typedef unordered_map<void*, cu_type_cache_t*> mod_cu_type_cache_t;
55 : :
56 : : // function -> die
57 : : typedef unordered_multimap<std::string, Dwarf_Die> cu_function_cache_t;
58 : : typedef std::pair<cu_function_cache_t::iterator,
59 : : cu_function_cache_t::iterator>
60 : : cu_function_cache_range_t;
61 : :
62 : : // cu die -> (function -> die)
63 : : typedef unordered_map<void*, cu_function_cache_t*> mod_cu_function_cache_t;
64 : :
65 : : // module -> (function -> die)
66 : : typedef unordered_map<Dwarf*, cu_function_cache_t*> mod_function_cache_t;
67 : :
68 : : // inline function die -> instance die[]
69 : : typedef unordered_map<void*, std::vector<Dwarf_Die>*> cu_inl_function_cache_t;
70 : :
71 : : // die -> parent die
72 : : typedef unordered_map<void*, Dwarf_Die> cu_die_parent_cache_t;
73 : :
74 : : // cu die -> (die -> parent die)
75 : : typedef unordered_map<void*, cu_die_parent_cache_t*> mod_cu_die_parent_cache_t;
76 : :
77 : : typedef std::vector<func_info> func_info_map_t;
78 : : typedef std::vector<inline_instance_info> inline_instance_map_t;
79 : :
80 : :
81 : : /* XXX FIXME functions that dwflpp needs from tapsets.cxx */
82 : : func_info_map_t *get_filtered_functions(dwarf_query *q);
83 : : inline_instance_map_t *get_filtered_inlines(dwarf_query *q);
84 : :
85 : :
86 : : struct
87 : : module_info
88 : : {
89 : : Dwfl_Module* mod;
90 : : const char* name;
91 : : std::string elf_path;
92 : : Dwarf_Addr addr;
93 : : Dwarf_Addr bias;
94 : : symbol_table *sym_table;
95 : : info_status dwarf_status; // module has dwarf info?
96 : : info_status symtab_status; // symbol table cached?
97 : :
98 : : void get_symtab(dwarf_query *q);
99 : : void update_symtab(cu_function_cache_t *funcs);
100 : :
101 : 4646 : module_info(const char *name) :
102 : : mod(NULL),
103 : : name(name),
104 : : addr(0),
105 : : bias(0),
106 : : sym_table(NULL),
107 : : dwarf_status(info_unknown),
108 : 4646 : symtab_status(info_unknown)
109 : 4646 : {}
110 : :
111 : : ~module_info();
112 : : };
113 : :
114 : :
115 : : struct
116 : : module_cache
117 : : {
118 : : std::map<std::string, module_info*> cache;
119 : : bool paths_collected;
120 : : bool dwarf_collected;
121 : :
122 : 645 : module_cache() : paths_collected(false), dwarf_collected(false) {}
123 : : ~module_cache();
124 : : };
125 : :
126 : :
127 : 10827270 : struct func_info
128 : : {
129 : 10420472 : func_info()
130 : : : decl_file(NULL), decl_line(-1), addr(0), entrypc(0), prologue_end(0),
131 : 10420472 : weak(false), descriptor(false)
132 : : {
133 : 10420472 : std::memset(&die, 0, sizeof(die));
134 : 10420472 : }
135 : : std::string name;
136 : : char const * decl_file;
137 : : int decl_line;
138 : : Dwarf_Die die;
139 : : Dwarf_Addr addr;
140 : : Dwarf_Addr entrypc;
141 : : Dwarf_Addr prologue_end;
142 : : bool weak, descriptor;
143 : : };
144 : :
145 : :
146 : 1081178 : struct inline_instance_info
147 : : {
148 : 213596 : inline_instance_info()
149 : 213596 : : decl_file(NULL), decl_line(-1), entrypc(0)
150 : : {
151 : 213596 : std::memset(&die, 0, sizeof(die));
152 : 213596 : }
153 : : bool operator<(const inline_instance_info& other) const;
154 : : std::string name;
155 : : char const * decl_file;
156 : : int decl_line;
157 : : Dwarf_Addr entrypc;
158 : : Dwarf_Die die;
159 : : };
160 : :
161 : :
162 : : struct dwflpp
163 : : {
164 : : systemtap_session & sess;
165 : :
166 : : // These are "current" values we focus on.
167 : : Dwfl_Module * module;
168 : : Dwarf_Addr module_bias;
169 : : module_info * mod_info;
170 : :
171 : : // These describe the current module's PC address range
172 : : Dwarf_Addr module_start;
173 : : Dwarf_Addr module_end;
174 : :
175 : : Dwarf_Die * cu;
176 : :
177 : : std::string module_name;
178 : : std::string function_name;
179 : :
180 : : dwflpp(systemtap_session & session, const std::string& user_module, bool kernel_p);
181 : : dwflpp(systemtap_session & session, const std::vector<std::string>& user_modules, bool kernel_p);
182 : : ~dwflpp();
183 : :
184 : : void get_module_dwarf(bool required = false, bool report = true);
185 : :
186 : : void focus_on_module(Dwfl_Module * m, module_info * mi);
187 : : void focus_on_cu(Dwarf_Die * c);
188 : : void focus_on_function(Dwarf_Die * f);
189 : :
190 : : std::string cu_name(void);
191 : :
192 : : Dwarf_Die *query_cu_containing_address(Dwarf_Addr a);
193 : :
194 : : bool module_name_matches(const std::string& pattern);
195 : : static bool name_has_wildcard(const std::string& pattern);
196 : : bool module_name_final_match(const std::string& pattern);
197 : :
198 : : bool function_name_matches_pattern(const std::string& name, const std::string& pattern);
199 : : bool function_name_matches(const std::string& pattern);
200 : : bool function_scope_matches(const std::vector<std::string>& scopes);
201 : :
202 : : void iterate_over_modules(int (* callback)(Dwfl_Module *, void **,
203 : : const char *, Dwarf_Addr,
204 : : void *),
205 : : void *data);
206 : :
207 : : void iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg),
208 : : void * data, bool want_types);
209 : :
210 : : bool func_is_inline();
211 : :
212 : : bool func_is_exported();
213 : :
214 : : void iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg),
215 : : void * data);
216 : :
217 : : std::vector<Dwarf_Die> getscopes_die(Dwarf_Die* die);
218 : : std::vector<Dwarf_Die> getscopes(Dwarf_Die* die);
219 : : std::vector<Dwarf_Die> getscopes(Dwarf_Addr pc);
220 : :
221 : : Dwarf_Die *declaration_resolve(Dwarf_Die *type);
222 : : Dwarf_Die *declaration_resolve(const std::string& name);
223 : : Dwarf_Die *declaration_resolve_other_cus(const std::string& name);
224 : :
225 : : int iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * q),
226 : : base_query * q, const std::string& function);
227 : :
228 : : int iterate_single_function (int (* callback)(Dwarf_Die * func, base_query * q),
229 : : base_query * q, const std::string& function);
230 : :
231 : : void iterate_over_srcfile_lines (char const * srcfile,
232 : : int lines[2],
233 : : bool need_single_match,
234 : : enum line_t line_type,
235 : : void (* callback) (const dwarf_line_t& line,
236 : : void * arg),
237 : : const std::string& func_pattern,
238 : : void *data);
239 : :
240 : : void iterate_over_labels (Dwarf_Die *begin_die,
241 : : const std::string& sym,
242 : : const std::string& function,
243 : : dwarf_query *q,
244 : : void (* callback)(const std::string &,
245 : : const char *,
246 : : const char *,
247 : : int,
248 : : Dwarf_Die *,
249 : : Dwarf_Addr,
250 : : dwarf_query *));
251 : :
252 : : int iterate_over_notes (void *object,
253 : : void (*callback)(void *object, int type,
254 : : const char *data, size_t len));
255 : :
256 : : void iterate_over_libraries (void (*callback)(void *object,
257 : : const char *data), void *data);
258 : :
259 : :
260 : : int iterate_over_plt (void *object,
261 : : void (*callback)(void *object, const char *name, size_t address));
262 : :
263 : : GElf_Shdr * get_section(std::string section_name, GElf_Shdr *shdr_mem,
264 : : Elf **elf_ret=NULL);
265 : :
266 : : void collect_srcfiles_matching (std::string const & pattern,
267 : : std::set<std::string> & filtered_srcfiles);
268 : :
269 : : void resolve_prologue_endings (func_info_map_t & funcs);
270 : :
271 : : bool function_entrypc (Dwarf_Addr * addr);
272 : : bool die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr);
273 : :
274 : : void function_die (Dwarf_Die *d);
275 : : void function_file (char const ** c);
276 : : void function_line (int *linep);
277 : :
278 : : bool die_has_pc (Dwarf_Die & die, Dwarf_Addr pc);
279 : : bool inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr,
280 : : Dwarf_Die& result);
281 : :
282 : : std::string literal_stmt_for_local (std::vector<Dwarf_Die>& scopes,
283 : : Dwarf_Addr pc,
284 : : std::string const & local,
285 : : const target_symbol *e,
286 : : bool lvalue,
287 : : exp_type & ty);
288 : : Dwarf_Die* type_die_for_local (std::vector<Dwarf_Die>& scopes,
289 : : Dwarf_Addr pc,
290 : : std::string const & local,
291 : : const target_symbol *e,
292 : : Dwarf_Die *die_mem);
293 : :
294 : : std::string literal_stmt_for_return (Dwarf_Die *scope_die,
295 : : Dwarf_Addr pc,
296 : : const target_symbol *e,
297 : : bool lvalue,
298 : : exp_type & ty);
299 : : Dwarf_Die* type_die_for_return (Dwarf_Die *scope_die,
300 : : Dwarf_Addr pc,
301 : : const target_symbol *e,
302 : : Dwarf_Die *die_mem);
303 : :
304 : : std::string literal_stmt_for_pointer (Dwarf_Die *type_die,
305 : : const target_symbol *e,
306 : : bool lvalue,
307 : : exp_type & ty);
308 : : Dwarf_Die* type_die_for_pointer (Dwarf_Die *type_die,
309 : : const target_symbol *e,
310 : : Dwarf_Die *die_mem);
311 : :
312 : : bool blacklisted_p(const std::string& funcname,
313 : : const std::string& filename,
314 : : int line,
315 : : const std::string& module,
316 : : Dwarf_Addr addr,
317 : : bool has_return);
318 : :
319 : : Dwarf_Addr relocate_address(Dwarf_Addr addr, std::string& reloc_section);
320 : :
321 : : void resolve_unqualified_inner_typedie (Dwarf_Die *typedie,
322 : : Dwarf_Die *innerdie,
323 : : const target_symbol *e);
324 : :
325 : :
326 : : private:
327 : : DwflPtr dwfl_ptr;
328 : :
329 : : // These are "current" values we focus on.
330 : : Dwarf * module_dwarf;
331 : : Dwarf_Die * function;
332 : :
333 : : void setup_kernel(const std::string& module_name, systemtap_session &s, bool debuginfo_needed = true);
334 : : void setup_kernel(const std::vector<std::string>& modules, bool debuginfo_needed = true);
335 : : void setup_user(const std::vector<std::string>& modules, bool debuginfo_needed = true);
336 : :
337 : : module_cu_cache_t module_cu_cache;
338 : : module_tus_read_t module_tus_read;
339 : : mod_cu_function_cache_t cu_function_cache;
340 : : mod_function_cache_t mod_function_cache;
341 : :
342 : : std::set<void*> cu_inl_function_cache_done; // CUs that are already cached
343 : : cu_inl_function_cache_t cu_inl_function_cache;
344 : : void cache_inline_instances (Dwarf_Die* die);
345 : :
346 : : mod_cu_die_parent_cache_t cu_die_parent_cache;
347 : : void cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die);
348 : : cu_die_parent_cache_t *get_die_parents();
349 : :
350 : : Dwarf_Die* get_parent_scope(Dwarf_Die* die);
351 : :
352 : : /* The global alias cache is used to resolve any DIE found in a
353 : : * module that is stubbed out with DW_AT_declaration with a defining
354 : : * DIE found in a different module. The current assumption is that
355 : : * this only applies to structures and unions, which have a global
356 : : * namespace (it deliberately only traverses program scope), so this
357 : : * cache is indexed by name. If other declaration lookups were
358 : : * added to it, it would have to be indexed by name and tag
359 : : */
360 : : mod_cu_type_cache_t global_alias_cache;
361 : : static int global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types,
362 : : const std::string& prefix, void *arg);
363 : : static int global_alias_caching_callback_cus(Dwarf_Die *die, void *arg);
364 : : static int iterate_over_globals (Dwarf_Die *,
365 : : int (* callback)(Dwarf_Die *, bool,
366 : : const std::string&, void *),
367 : : void * data);
368 : : static int iterate_over_types (Dwarf_Die *, bool, const std::string&,
369 : : int (* callback)(Dwarf_Die *, bool,
370 : : const std::string&, void *),
371 : : void * data);
372 : :
373 : : static int mod_function_caching_callback (Dwarf_Die* func, void *arg);
374 : : static int cu_function_caching_callback (Dwarf_Die* func, void *arg);
375 : :
376 : : bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno);
377 : :
378 : : static void loc2c_error (void *, const char *fmt, ...) __attribute__ ((noreturn));
379 : :
380 : : // This function generates code used for addressing computations of
381 : : // target variables.
382 : : void emit_address (struct obstack *pool, Dwarf_Addr address);
383 : : static void loc2c_emit_address (void *arg, struct obstack *pool,
384 : : Dwarf_Addr address);
385 : :
386 : : void print_locals(std::vector<Dwarf_Die>& scopes, std::ostream &o);
387 : : void print_locals_die(Dwarf_Die &die, std::ostream &o);
388 : : void print_members(Dwarf_Die *vardie, std::ostream &o,
389 : : std::set<std::string> &dupes);
390 : :
391 : : Dwarf_Attribute *find_variable_and_frame_base (std::vector<Dwarf_Die>& scopes,
392 : : Dwarf_Addr pc,
393 : : std::string const & local,
394 : : const target_symbol *e,
395 : : Dwarf_Die *vardie,
396 : : Dwarf_Attribute *fb_attr_mem);
397 : :
398 : : struct location *translate_location(struct obstack *pool,
399 : : Dwarf_Attribute *attr,
400 : : Dwarf_Die *die,
401 : : Dwarf_Addr pc,
402 : : Dwarf_Attribute *fb_attr,
403 : : struct location **tail,
404 : : const target_symbol *e);
405 : :
406 : : bool find_struct_member(const target_symbol::component& c,
407 : : Dwarf_Die *parentdie,
408 : : Dwarf_Die *memberdie,
409 : : std::vector<Dwarf_Die>& dies,
410 : : std::vector<Dwarf_Attribute>& locs);
411 : :
412 : : void translate_components(struct obstack *pool,
413 : : struct location **tail,
414 : : Dwarf_Addr pc,
415 : : const target_symbol *e,
416 : : Dwarf_Die *vardie,
417 : : Dwarf_Die *typedie,
418 : : unsigned first=0);
419 : :
420 : : void translate_final_fetch_or_store (struct obstack *pool,
421 : : struct location **tail,
422 : : Dwarf_Addr module_bias,
423 : : Dwarf_Die *vardie,
424 : : Dwarf_Die *typedie,
425 : : bool lvalue,
426 : : const target_symbol *e,
427 : : std::string &,
428 : : std::string &,
429 : : exp_type & ty);
430 : :
431 : : std::string express_as_string (std::string prelude,
432 : : std::string postlude,
433 : : struct location *head);
434 : :
435 : : regex_t blacklist_func; // function/statement probes
436 : : regex_t blacklist_func_ret; // only for .return probes
437 : : regex_t blacklist_file; // file name
438 : : regex_t blacklist_section; // init/exit sections
439 : : bool blacklist_enabled;
440 : : void build_blacklist();
441 : : std::string get_blacklist_section(Dwarf_Addr addr);
442 : :
443 : : // Returns the call frame address operations for the given program counter.
444 : : Dwarf_Op *get_cfa_ops (Dwarf_Addr pc);
445 : :
446 : : Dwarf_Addr vardie_from_symtable(Dwarf_Die *vardie, Dwarf_Addr *addr);
447 : :
448 : : static int add_module_build_id_to_hash (Dwfl_Module *m,
449 : : void **userdata __attribute__ ((unused)),
450 : : const char *name,
451 : : Dwarf_Addr base,
452 : : void *arg);
453 : :
454 : : public:
455 : : Dwarf_Addr pr15123_retry_addr (Dwarf_Addr pc, Dwarf_Die* var);
456 : : };
457 : :
458 : : #endif // DWFLPP_H
459 : :
460 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|