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 : : #include "dwflpp.h"
12 : : #include "config.h"
13 : : #include "staptree.h"
14 : : #include "elaborate.h"
15 : : #include "tapsets.h"
16 : : #include "task_finder.h"
17 : : #include "translate.h"
18 : : #include "session.h"
19 : : #include "util.h"
20 : : #include "buildrun.h"
21 : : #include "dwarf_wrappers.h"
22 : : #include "auto_free.h"
23 : : #include "hash.h"
24 : : #include "rpm_finder.h"
25 : : #include "setupdwfl.h"
26 : :
27 : : #include <cstdlib>
28 : : #include <algorithm>
29 : : #include <deque>
30 : : #include <iostream>
31 : : #include <map>
32 : : #include <set>
33 : : #include <sstream>
34 : : #include <stdexcept>
35 : : #include <vector>
36 : : #include <cstdarg>
37 : : #include <cassert>
38 : : #include <iomanip>
39 : : #include <cerrno>
40 : :
41 : : extern "C" {
42 : : #include <fcntl.h>
43 : : #include <elfutils/libdwfl.h>
44 : : #include <elfutils/libdw.h>
45 : : #include <dwarf.h>
46 : : #include <elf.h>
47 : : #include <obstack.h>
48 : : #include <regex.h>
49 : : #include <glob.h>
50 : : #include <fnmatch.h>
51 : : #include <stdio.h>
52 : : #include <sys/types.h>
53 : :
54 : : #include "loc2c.h"
55 : : #define __STDC_FORMAT_MACROS
56 : : #include <inttypes.h>
57 : : }
58 : :
59 : : // Older glibc elf.h don't know about this new constant.
60 : : #ifndef STB_GNU_UNIQUE
61 : : #define STB_GNU_UNIQUE 10
62 : : #endif
63 : :
64 : :
65 : : // debug flag to compare to the uncached version from libdw
66 : : // #define DEBUG_DWFLPP_GETSCOPES 1
67 : :
68 : :
69 : : using namespace std;
70 : : using namespace __gnu_cxx;
71 : :
72 : :
73 [ + - ]: 2414 : static string TOK_KERNEL("kernel");
74 : :
75 : :
76 : 1041 : dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p):
77 : : sess(session), module(NULL), module_bias(0), mod_info(NULL),
78 : : module_start(0), module_end(0), cu(NULL),
79 : : module_dwarf(NULL), function(NULL), blacklist_func(), blacklist_func_ret(),
80 [ + - ][ + - ]: 1041 : blacklist_file(), blacklist_enabled(false)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
81 : : {
82 [ + + ]: 1041 : if (kernel_p)
83 [ + + ]: 972 : setup_kernel(name, session);
84 : : else
85 : : {
86 [ + - ]: 69 : vector<string> modules;
87 [ + - ]: 69 : modules.push_back(name);
88 [ + - ][ + - ]: 69 : setup_user(modules);
89 : : }
90 : 1041 : }
91 : :
92 : 84 : dwflpp::dwflpp(systemtap_session & session, const vector<string>& names,
93 : : bool kernel_p):
94 : : sess(session), module(NULL), module_bias(0), mod_info(NULL),
95 : : module_start(0), module_end(0), cu(NULL),
96 [ + - ][ + - ]: 84 : module_dwarf(NULL), function(NULL), blacklist_enabled(false)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
97 : : {
98 [ + - ]: 84 : if (kernel_p)
99 [ + - ]: 84 : setup_kernel(names);
100 : : else
101 [ # # ]: 0 : setup_user(names);
102 : 84 : }
103 : :
104 : 13476 : dwflpp::~dwflpp()
105 : : {
106 [ + - ]: 1123 : delete_map(module_cu_cache);
107 [ + - ]: 1123 : delete_map(cu_function_cache);
108 [ + - ]: 1123 : delete_map(mod_function_cache);
109 [ + - ]: 1123 : delete_map(cu_inl_function_cache);
110 [ + - ]: 1123 : delete_map(global_alias_cache);
111 [ + - ]: 1123 : delete_map(cu_die_parent_cache);
112 : :
113 [ + - ]: 1123 : dwfl_ptr.reset();
114 : : // NB: don't "delete mod_info;", as that may be shared
115 : : // between dwflpp instances, and are stored in
116 : : // session.module_cache[] anyway.
117 [ + - ][ + - ]: 1123 : }
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
118 : :
119 : :
120 : 1286 : module_cache::~module_cache ()
121 : : {
122 [ + - ]: 643 : delete_map(cache);
123 : 643 : }
124 : :
125 : :
126 : : void
127 : 414373 : dwflpp::get_module_dwarf(bool required, bool report)
128 : : {
129 : 414373 : module_dwarf = dwfl_module_getdwarf(module, &module_bias);
130 [ + + ]: 414373 : mod_info->dwarf_status = (module_dwarf ? info_present : info_absent);
131 [ + + ][ + - ]: 414373 : if (!module_dwarf && report)
132 : : {
133 [ + - ]: 8 : string msg = _("cannot find ");
134 [ + - ][ - + ]: 8 : if (module_name == "")
135 [ # # ]: 0 : msg += "kernel";
136 : : else
137 [ + - ][ + - ]: 8 : msg += string("module ") + module_name;
[ + - ][ + - ]
[ + - ]
138 [ + - ]: 8 : msg += " debuginfo";
139 : :
140 [ + - ]: 8 : int i = dwfl_errno();
141 [ + - ]: 8 : if (i)
142 [ + - ][ + - ]: 8 : msg += string(": ") + dwfl_errmsg (i);
[ + - ][ + - ]
[ + - ][ + - ]
143 : :
144 [ + - ]: 8 : msg += " [man warning::debuginfo]";
145 : :
146 : : /* add module_name to list to find rpm */
147 [ + - ][ + - ]: 8 : find_debug_rpms(sess, module_name.c_str());
148 : :
149 [ - + ]: 8 : if (required)
150 [ # # ]: 0 : throw semantic_error (msg);
151 : : else
152 [ + - ][ + - ]: 8 : sess.print_warning(msg);
153 : : }
154 : 414373 : }
155 : :
156 : :
157 : : void
158 : 85120 : dwflpp::focus_on_module(Dwfl_Module * m, module_info * mi)
159 : : {
160 : 85120 : module = m;
161 : 85120 : mod_info = mi;
162 [ + - ]: 85120 : if (m)
163 : : {
164 : : module_name = dwfl_module_info(module, NULL, &module_start, &module_end,
165 [ + - ]: 85120 : NULL, NULL, NULL, NULL) ?: "module";
166 : : }
167 : : else
168 : : {
169 [ # # ][ # # ]: 0 : assert(mi && mi->name && mi->name == TOK_KERNEL);
[ # # ]
170 : 0 : module_name = mi->name;
171 : 0 : module_start = 0;
172 : 0 : module_end = 0;
173 : 0 : module_bias = mi->bias;
174 : : }
175 : :
176 : : // Reset existing pointers and names
177 : :
178 : 85120 : module_dwarf = NULL;
179 : :
180 : 85120 : cu = NULL;
181 : :
182 : 85120 : function_name.clear();
183 : 85120 : function = NULL;
184 : 85120 : }
185 : :
186 : :
187 : : void
188 : 265398 : dwflpp::focus_on_cu(Dwarf_Die * c)
189 : : {
190 [ - + ]: 265398 : assert(c);
191 [ - + ]: 265398 : assert(module);
192 : :
193 : 265398 : cu = c;
194 : :
195 : : // Reset existing pointers and names
196 : 265398 : function_name.clear();
197 : 265398 : function = NULL;
198 : 265398 : }
199 : :
200 : :
201 : : string
202 : 0 : dwflpp::cu_name(void)
203 : : {
204 [ # # ][ # # ]: 0 : return dwarf_diename(cu) ?: "<unknown source>";
205 : : }
206 : :
207 : :
208 : : void
209 : 698033 : dwflpp::focus_on_function(Dwarf_Die * f)
210 : : {
211 [ - + ]: 698033 : assert(f);
212 [ - + ]: 698033 : assert(module);
213 [ - + ]: 698033 : assert(cu);
214 : :
215 : 698033 : function = f;
216 [ + - ]: 698033 : function_name = dwarf_diename(function) ?: "function";
217 : 698033 : }
218 : :
219 : :
220 : : /* Return the Dwarf_Die for the given address in the current module.
221 : : * The address should be in the module address address space (this
222 : : * function will take care of any dw bias).
223 : : */
224 : : Dwarf_Die *
225 : 25 : dwflpp::query_cu_containing_address(Dwarf_Addr a)
226 : : {
227 : : Dwarf_Addr bias;
228 [ - + ]: 25 : assert(dwfl_ptr.get()->dwfl);
229 [ - + ]: 25 : assert(module);
230 [ + - ]: 25 : get_module_dwarf();
231 : :
232 [ + - ]: 25 : Dwarf_Die* cudie = dwfl_module_addrdie(module, a, &bias);
233 [ - + ]: 25 : assert(bias == module_bias);
234 : 25 : return cudie;
235 : : }
236 : :
237 : :
238 : : bool
239 : 85119 : dwflpp::module_name_matches(const string& pattern)
240 : : {
241 : 85119 : bool t = (fnmatch(pattern.c_str(), module_name.c_str(), 0) == 0);
242 [ + + ][ - + ]: 85119 : if (t && sess.verbose>3)
243 : 0 : clog << _F("pattern '%s' matches module '%s'\n",
244 [ # # ]: 0 : pattern.c_str(), module_name.c_str());
245 : 85119 : return t;
246 : : }
247 : :
248 : :
249 : : bool
250 : 194823 : dwflpp::name_has_wildcard (const string& pattern)
251 : : {
252 : 194823 : return (pattern.find('*') != string::npos ||
253 : 131060 : pattern.find('?') != string::npos ||
254 [ + + + - ]: 325883 : pattern.find('[') != string::npos);
[ + + ]
255 : : }
256 : :
257 : :
258 : : bool
259 : 79135 : dwflpp::module_name_final_match(const string& pattern)
260 : : {
261 : : // Assume module_name_matches(). Can there be any more matches?
262 : : // Not unless the pattern is a wildcard, since module names are
263 : : // presumed unique.
264 : 79135 : return !name_has_wildcard(pattern);
265 : : }
266 : :
267 : :
268 : : bool
269 : 2774840 : dwflpp::function_name_matches_pattern(const string& name, const string& pattern)
270 : : {
271 : 2774840 : bool t = (fnmatch(pattern.c_str(), name.c_str(), 0) == 0);
272 [ + + ][ - + ]: 2774840 : if (t && sess.verbose>3)
273 [ # # ]: 0 : clog << _F("pattern '%s' matches function '%s'\n", pattern.c_str(), name.c_str());
274 : 2774840 : return t;
275 : : }
276 : :
277 : :
278 : : bool
279 : 746 : dwflpp::function_name_matches(const string& pattern)
280 : : {
281 [ - + ]: 746 : assert(function);
282 : 746 : return function_name_matches_pattern(function_name, pattern);
283 : : }
284 : :
285 : :
286 : : bool
287 : 696083 : dwflpp::function_scope_matches(const vector<string>& scopes)
288 : : {
289 : : // walk up the containing scopes
290 : 696083 : Dwarf_Die* die = function;
291 [ - + ]: 696083 : for (int i = scopes.size() - 1; i >= 0; --i)
292 : : {
293 [ # # ]: 0 : die = get_parent_scope(die);
294 : :
295 : : // check if this scope matches, and prepend it if so
296 : : // NB: a NULL die is the global scope, compared as ""
297 [ # # ][ # # ]: 0 : string name = dwarf_diename(die) ?: "";
[ # # ]
298 [ # # ]: 0 : if (name_has_wildcard(scopes[i]) ?
[ # # # # ]
[ # # ][ # # ]
299 : 0 : function_name_matches_pattern(name, scopes[i]) :
300 : 0 : name == scopes[i])
301 [ # # ][ # # ]: 0 : function_name = name + "::" + function_name;
[ # # ][ # # ]
[ # # ]
302 : : else
303 : 0 : return false;
304 : :
305 : : // make sure there's no more if we're at the global scope
306 [ # # ][ # # ]: 0 : if (!die && i > 0)
307 : 0 : return false;
308 [ # # ][ # # ]: 0 : }
309 : 696083 : return true;
310 : : }
311 : :
312 : :
313 : : void
314 : 972 : dwflpp::setup_kernel(const string& name, systemtap_session & s, bool debuginfo_needed)
315 : : {
316 [ + + ]: 972 : if (! sess.module_cache)
317 [ + - ][ + - ]: 531 : sess.module_cache = new module_cache ();
318 : :
319 : 972 : unsigned offline_search_matches = 0;
320 [ + - ][ + - ]: 972 : dwfl_ptr = setup_dwfl_kernel(name, &offline_search_matches, sess);
[ + - ]
321 : :
322 [ + + ]: 972 : if (offline_search_matches < 1)
323 : : {
324 [ + - ]: 2 : if (debuginfo_needed) {
325 : : // Suggest a likely kernel dir to find debuginfo rpm for
326 [ + - ][ + - ]: 2 : string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release );
[ + - ]
327 [ + - ][ + - ]: 2 : find_debug_rpms(sess, dir.c_str());
[ + - ]
328 : : }
329 : 2 : throw semantic_error (_F("missing %s kernel/module debuginfo [man warning::debuginfo] under '%s'",
330 [ + - ][ + - ]: 2 : sess.architecture.c_str(), sess.kernel_build_tree.c_str()));
[ + - ][ + - ]
331 : : }
332 : 970 : Dwfl *dwfl = dwfl_ptr.get()->dwfl;
333 [ + - ]: 970 : if (dwfl != NULL)
334 : : {
335 : 970 : ptrdiff_t off = 0;
336 [ - + ]: 970 : do
337 : : {
338 [ + - ]: 970 : assert_no_interrupts();
339 [ + - ]: 970 : off = dwfl_getmodules (dwfl, &add_module_build_id_to_hash, &s, off);
340 : : }
341 : : while (off > 0);
342 [ + - ][ + - ]: 972 : dwfl_assert("dwfl_getmodules", off == 0);
[ + - ]
343 : : }
344 : :
345 [ + - ]: 970 : build_blacklist();
346 : 970 : }
347 : :
348 : : void
349 : 84 : dwflpp::setup_kernel(const vector<string> &names, bool debuginfo_needed)
350 : : {
351 [ + + ]: 84 : if (! sess.module_cache)
352 [ + - ][ + - ]: 65 : sess.module_cache = new module_cache ();
353 : :
354 : 84 : unsigned offline_search_matches = 0;
355 [ + - ][ + - ]: 84 : set<string> offline_search_names(names.begin(), names.end());
[ + - ]
356 : : dwfl_ptr = setup_dwfl_kernel(offline_search_names,
357 : : &offline_search_matches,
358 [ + - ][ + - ]: 84 : sess);
[ + - ]
359 : :
360 [ + - ][ - + ]: 84 : if (offline_search_matches < offline_search_names.size())
361 : : {
362 [ # # ]: 0 : if (debuginfo_needed) {
363 : : // Suggest a likely kernel dir to find debuginfo rpm for
364 [ # # ][ # # ]: 0 : string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release );
[ # # ]
365 [ # # ][ # # ]: 0 : find_debug_rpms(sess, dir.c_str());
[ # # ]
366 : : }
367 : 0 : throw semantic_error (_F("missing %s kernel/module debuginfo [man warning::debuginfo] under '%s'",
368 [ # # ][ # # ]: 0 : sess.architecture.c_str(), sess.kernel_build_tree.c_str()));
[ # # ][ # # ]
369 : : }
370 : :
371 [ + - ][ + - ]: 84 : build_blacklist();
372 : 84 : }
373 : :
374 : :
375 : : void
376 : 69 : dwflpp::setup_user(const vector<string>& modules, bool debuginfo_needed)
377 : : {
378 [ + + ]: 69 : if (! sess.module_cache)
379 [ + - ][ + - ]: 49 : sess.module_cache = new module_cache ();
380 : :
381 [ + - ]: 69 : vector<string>::const_iterator it = modules.begin();
382 [ + - ][ + - ]: 69 : dwfl_ptr = setup_dwfl_user(it, modules.end(), debuginfo_needed, sess);
[ + - ][ + - ]
383 [ + - ][ + - ]: 69 : if (debuginfo_needed && it != modules.end())
[ + - ][ - + ]
[ + - ]
[ - + # # ]
384 : 0 : dwfl_assert (string(_F("missing process %s %s debuginfo",
385 : : (*it).c_str(), sess.architecture.c_str())),
386 [ # # ][ # # ]: 0 : dwfl_ptr.get()->dwfl);
[ # # ][ # # ]
[ # # ]
387 : 69 : }
388 : :
389 : : void
390 : 56812 : dwflpp::iterate_over_modules(int (* callback)(Dwfl_Module *, void **,
391 : : const char *, Dwarf_Addr,
392 : : void *),
393 : : void *data)
394 : : {
395 : 56812 : dwfl_getmodules (dwfl_ptr.get()->dwfl, callback, data, 0);
396 : :
397 : : // Don't complain if we exited dwfl_getmodules early.
398 : : // This could be a $target variable error that will be
399 : : // reported soon anyway.
400 : : // dwfl_assert("dwfl_getmodules", off == 0);
401 : :
402 : : // PR6864 XXX: For dwarfless case (if .../vmlinux is missing), then the
403 : : // "kernel" module is not reported in the loop above. However, we
404 : : // may be able to make do with symbol table data.
405 : 56812 : }
406 : :
407 : :
408 : : void
409 : 44955 : dwflpp::iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg),
410 : : void * data, bool want_types)
411 : : {
412 [ + - ]: 44955 : get_module_dwarf(false);
413 : 44955 : Dwarf *dw = module_dwarf;
414 [ + - ]: 89910 : if (!dw) return;
415 : :
416 [ + - ]: 44955 : vector<Dwarf_Die>* v = module_cu_cache[dw];
417 [ + + ]: 44955 : if (v == 0)
418 : : {
419 [ + - ][ + - ]: 4527 : v = new vector<Dwarf_Die>;
420 [ + - ]: 4527 : module_cu_cache[dw] = v;
421 : :
422 : 4527 : Dwarf_Off off = 0;
423 : : size_t cuhl;
424 : : Dwarf_Off noff;
425 [ + - ][ + + ]: 655608 : while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
426 : : {
427 [ + - ]: 651081 : assert_no_interrupts();
428 : : Dwarf_Die die_mem;
429 : : Dwarf_Die *die;
430 [ + - ]: 651081 : die = dwarf_offdie (dw, off + cuhl, &die_mem);
431 : : /* Skip partial units. */
432 [ + - ][ + - ]: 651081 : if (dwarf_tag (die) == DW_TAG_compile_unit)
433 [ + - ]: 651081 : v->push_back (*die); /* copy */
434 : 651081 : off = noff;
435 : : }
436 : : }
437 : :
438 [ + + ][ + - ]: 44955 : if (want_types && module_tus_read.find(dw) == module_tus_read.end())
[ + - ][ + + ]
[ + + ][ + + ]
[ + + # #
# # ]
439 : : {
440 : : // Process type units.
441 : 678 : Dwarf_Off off = 0;
442 : : size_t cuhl;
443 : : Dwarf_Off noff;
444 : : uint64_t type_signature;
445 [ + + ]: 1357 : while (dwarf_next_unit (dw, off, &noff, &cuhl, NULL, NULL, NULL, NULL,
446 [ + - ]: 679 : &type_signature, NULL) == 0)
447 : : {
448 [ + - ]: 1 : assert_no_interrupts();
449 : : Dwarf_Die die_mem;
450 : : Dwarf_Die *die;
451 [ + - ]: 1 : die = dwarf_offdie_types (dw, off + cuhl, &die_mem);
452 : : /* Skip partial units. */
453 [ + - ][ + - ]: 1 : if (dwarf_tag (die) == DW_TAG_type_unit)
454 [ + - ]: 1 : v->push_back (*die); /* copy */
455 : 1 : off = noff;
456 : : }
457 [ + - ]: 678 : module_tus_read.insert(dw);
458 : : }
459 : :
460 [ + - ][ + - ]: 13977428 : for (vector<Dwarf_Die>::iterator i = v->begin(); i != v->end(); ++i)
[ + - ][ + + ]
461 : : {
462 [ + - ]: 13932473 : int rc = (*callback)(&*i, data);
463 [ + - ]: 13932473 : assert_no_interrupts();
464 [ + + ]: 13932473 : if (rc != DWARF_CB_OK)
465 : 1 : break;
466 : : }
467 : : }
468 : :
469 : :
470 : : bool
471 : 2590110 : dwflpp::func_is_inline()
472 : : {
473 [ - + ]: 2590110 : assert (function);
474 : 2590110 : return dwarf_func_inline (function) != 0;
475 : : }
476 : :
477 : :
478 : : bool
479 : 40 : dwflpp::func_is_exported()
480 : : {
481 [ - + ]: 40 : const char *name = dwarf_linkage_name (function) ?: dwarf_diename (function);
482 : :
483 [ - + ]: 40 : assert (function);
484 : :
485 : 40 : int syms = dwfl_module_getsymtab (module);
486 [ + - ][ + - ]: 40 : dwfl_assert (_("Getting symbols"), syms >= 0);
[ + - ]
487 : :
488 [ + + ]: 3662184 : for (int i = 0; i < syms; i++)
489 : : {
490 : : GElf_Sym sym;
491 : : GElf_Word shndxp;
492 [ + - ]: 3662144 : const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp);
493 [ + - ][ + + ]: 3662144 : if (symname
494 : 3662144 : && strcmp (name, symname) == 0)
495 : : {
496 [ + - ][ + + ]: 39 : if (GELF_ST_TYPE(sym.st_info) == STT_FUNC
[ + - ][ - + ]
497 : : && (GELF_ST_BIND(sym.st_info) == STB_GLOBAL
498 : : || GELF_ST_BIND(sym.st_info) == STB_WEAK
499 : : || GELF_ST_BIND(sym.st_info) == STB_GNU_UNIQUE))
500 : 34 : return true;
501 : : else
502 : 5 : return false;
503 : : }
504 : : }
505 : 40 : return false;
506 : : }
507 : :
508 : : void
509 : 393799 : dwflpp::cache_inline_instances (Dwarf_Die* die)
510 : : {
511 : : // If this is an inline instance, link it back to its origin
512 : : Dwarf_Die origin;
513 [ + - ][ + + ]: 520121 : if (dwarf_tag(die) == DW_TAG_inlined_subroutine &&
[ + - ][ + + ]
514 [ + - ]: 126322 : dwarf_attr_die(die, DW_AT_abstract_origin, &origin))
515 : : {
516 [ + - ]: 126322 : vector<Dwarf_Die>*& v = cu_inl_function_cache[origin.addr];
517 [ + + ]: 126322 : if (!v)
518 [ + - ][ + - ]: 47263 : v = new vector<Dwarf_Die>;
519 [ + - ]: 126322 : v->push_back(*die);
520 : : }
521 : :
522 : : // Recurse through other scopes that may contain inlines
523 : : Dwarf_Die child, import;
524 [ + - ][ + + ]: 393799 : if (dwarf_child(die, &child) == 0)
525 [ + + ]: 3624555 : do
526 : : {
527 [ + - ]: 3624555 : switch (dwarf_tag (&child))
[ + - + ]
528 : : {
529 : : // tags that could contain inlines
530 : : case DW_TAG_compile_unit:
531 : : case DW_TAG_module:
532 : : case DW_TAG_lexical_block:
533 : : case DW_TAG_with_stmt:
534 : : case DW_TAG_catch_block:
535 : : case DW_TAG_try_block:
536 : : case DW_TAG_entry_point:
537 : : case DW_TAG_inlined_subroutine:
538 : : case DW_TAG_subprogram:
539 [ + - ]: 392064 : cache_inline_instances(&child);
540 : 392064 : break;
541 : :
542 : : // imported dies should be followed
543 : : case DW_TAG_imported_unit:
544 [ # # ][ # # ]: 0 : if (dwarf_attr_die(&child, DW_AT_import, &import))
545 [ # # ]: 0 : cache_inline_instances(&import);
546 : 0 : break;
547 : :
548 : : // nothing to do for other tags
549 : : default:
550 : 3232491 : break;
551 : : }
552 : : }
553 [ + - ]: 3624555 : while (dwarf_siblingof(&child, &child) == 0);
554 : 393799 : }
555 : :
556 : :
557 : : void
558 : 111376 : dwflpp::iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg),
559 : : void * data)
560 : : {
561 [ - + ]: 111376 : assert (function);
562 [ - + ]: 111376 : assert (func_is_inline ());
563 : :
564 [ + + ]: 111376 : if (cu_inl_function_cache_done.insert(cu->addr).second)
565 : 1735 : cache_inline_instances(cu);
566 : :
567 : 111376 : vector<Dwarf_Die>* v = cu_inl_function_cache[function->addr];
568 [ + + ]: 111376 : if (!v)
569 : 111376 : return;
570 : :
571 [ + - ][ + - ]: 295020 : for (vector<Dwarf_Die>::iterator i = v->begin(); i != v->end(); ++i)
[ + - ][ + + ]
572 : : {
573 [ + - ]: 213596 : int rc = (*callback)(&*i, data);
574 [ + - ]: 213596 : assert_no_interrupts();
575 [ - + ]: 213596 : if (rc != DWARF_CB_OK)
576 : 0 : break;
577 : : }
578 : : }
579 : :
580 : :
581 : : void
582 : 6247086 : dwflpp::cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die)
583 : : {
584 : : // Record and recurse through DIEs we care about
585 : : Dwarf_Die child, import;
586 [ + - ][ + + ]: 6247086 : if (dwarf_child(die, &child) == 0)
587 [ + + ]: 42063955 : do
588 : : {
589 [ + - ]: 42063955 : switch (dwarf_tag (&child))
[ + + - + ]
590 : : {
591 : : // normal tags to recurse
592 : : case DW_TAG_compile_unit:
593 : : case DW_TAG_module:
594 : : case DW_TAG_lexical_block:
595 : : case DW_TAG_with_stmt:
596 : : case DW_TAG_catch_block:
597 : : case DW_TAG_try_block:
598 : : case DW_TAG_entry_point:
599 : : case DW_TAG_inlined_subroutine:
600 : : case DW_TAG_subprogram:
601 : : case DW_TAG_namespace:
602 : : case DW_TAG_class_type:
603 : : case DW_TAG_structure_type:
604 [ + - ][ + - ]: 6237602 : parents->insert(make_pair(child.addr, *die));
605 [ + - ]: 6237602 : cache_die_parents(parents, &child);
606 : 6237602 : break;
607 : :
608 : : // record only, nothing to recurse
609 : : case DW_TAG_label:
610 [ + - ][ + - ]: 118334 : parents->insert(make_pair(child.addr, *die));
611 : 118334 : break;
612 : :
613 : : // imported dies should be followed
614 : : case DW_TAG_imported_unit:
615 [ # # ][ # # ]: 0 : if (dwarf_attr_die(&child, DW_AT_import, &import))
616 : : {
617 [ # # ][ # # ]: 0 : parents->insert(make_pair(import.addr, *die));
618 [ # # ]: 0 : cache_die_parents(parents, &import);
619 : : }
620 : 0 : break;
621 : :
622 : : // nothing to do for other tags
623 : : default:
624 : 35708019 : break;
625 : : }
626 : : }
627 [ + - ]: 42063955 : while (dwarf_siblingof(&child, &child) == 0);
628 : 6247086 : }
629 : :
630 : :
631 : : cu_die_parent_cache_t*
632 : 67022 : dwflpp::get_die_parents()
633 : : {
634 [ - + ]: 67022 : assert (cu);
635 : :
636 : 67022 : cu_die_parent_cache_t *& parents = cu_die_parent_cache[cu->addr];
637 [ + + ]: 67022 : if (!parents)
638 : : {
639 [ + - ][ + - ]: 9484 : parents = new cu_die_parent_cache_t;
640 : 9484 : cache_die_parents(parents, cu);
641 [ - + ]: 9484 : if (sess.verbose > 4)
642 [ # # ][ # # ]: 0 : clog << _F("die parent cache %s:%s size %zu", module_name.c_str(),
[ # # ][ # # ]
643 [ # # ]: 0 : cu_name().c_str(), parents->size()) << endl;
644 : : }
645 : 67022 : return parents;
646 : : }
647 : :
648 : :
649 : : vector<Dwarf_Die>
650 : 684 : dwflpp::getscopes_die(Dwarf_Die* die)
651 : : {
652 [ + - ]: 684 : cu_die_parent_cache_t *parents = get_die_parents();
653 : :
654 [ + - ]: 684 : vector<Dwarf_Die> scopes;
655 : 684 : Dwarf_Die *scope = die;
656 [ + - ]: 684 : cu_die_parent_cache_t::iterator it;
657 [ + + ]: 2066 : do
658 : : {
659 [ + - ]: 2066 : scopes.push_back(*scope);
660 [ + - ]: 2066 : it = parents->find(scope->addr);
661 [ + - ]: 2066 : scope = &it->second;
662 : : }
663 [ + - ]: 2066 : while (it != parents->end());
664 : :
665 : : #ifdef DEBUG_DWFLPP_GETSCOPES
666 : : Dwarf_Die *dscopes = NULL;
667 : : int nscopes = dwarf_getscopes_die(die, &dscopes);
668 : :
669 : : assert(nscopes == (int)scopes.size());
670 : : for (unsigned i = 0; i < scopes.size(); ++i)
671 : : assert(scopes[i].addr == dscopes[i].addr);
672 : : free(dscopes);
673 : : #endif
674 : :
675 : 684 : return scopes;
676 : : }
677 : :
678 : :
679 : : std::vector<Dwarf_Die>
680 : 66338 : dwflpp::getscopes(Dwarf_Die* die)
681 : : {
682 [ + - ]: 66338 : cu_die_parent_cache_t *parents = get_die_parents();
683 : :
684 [ + - ]: 66338 : vector<Dwarf_Die> scopes;
685 : :
686 : : Dwarf_Die origin;
687 : 66338 : Dwarf_Die *scope = die;
688 [ + - ]: 66338 : cu_die_parent_cache_t::iterator it;
689 [ + + ]: 132714 : do
690 : : {
691 [ + - ]: 132714 : scopes.push_back(*scope);
692 [ + - ][ + + ]: 133007 : if (dwarf_tag(scope) == DW_TAG_inlined_subroutine &&
[ + - ][ + + ]
693 [ + - ]: 293 : dwarf_attr_die(scope, DW_AT_abstract_origin, &origin))
694 : 293 : scope = &origin;
695 : :
696 [ + - ]: 132714 : it = parents->find(scope->addr);
697 [ + - ]: 132714 : scope = &it->second;
698 : : }
699 [ + - ]: 132714 : while (it != parents->end());
700 : :
701 : : #ifdef DEBUG_DWFLPP_GETSCOPES
702 : : // there isn't an exact libdw equivalent, but if dwarf_getscopes on the
703 : : // entrypc returns the same first die, then all the scopes should match
704 : : Dwarf_Addr pc;
705 : : if (die_entrypc(die, &pc))
706 : : {
707 : : Dwarf_Die *dscopes = NULL;
708 : : int nscopes = dwarf_getscopes(cu, pc, &dscopes);
709 : : if (nscopes > 0 && dscopes[0].addr == die->addr)
710 : : {
711 : : assert(nscopes == (int)scopes.size());
712 : : for (unsigned i = 0; i < scopes.size(); ++i)
713 : : assert(scopes[i].addr == dscopes[i].addr);
714 : : }
715 : : free(dscopes);
716 : : }
717 : : #endif
718 : :
719 : 66338 : return scopes;
720 : : }
721 : :
722 : :
723 : : std::vector<Dwarf_Die>
724 : 25 : dwflpp::getscopes(Dwarf_Addr pc)
725 : : {
726 : : // The die_parent_cache doesn't help us without knowing where the pc is
727 : : // contained, so we have to do this one the old fashioned way.
728 : :
729 [ - + ]: 25 : assert (cu);
730 : :
731 [ + - ]: 25 : vector<Dwarf_Die> scopes;
732 : :
733 : : Dwarf_Die* dwarf_scopes;
734 [ + - ]: 25 : int nscopes = dwarf_getscopes(cu, pc, &dwarf_scopes);
735 [ + - ]: 25 : if (nscopes > 0)
736 : : {
737 [ + - ]: 25 : scopes.assign(dwarf_scopes, dwarf_scopes + nscopes);
738 : 25 : free(dwarf_scopes);
739 : : }
740 : :
741 : : #ifdef DEBUG_DWFLPP_GETSCOPES
742 : : // check that getscopes on the starting die gets the same result
743 : : if (!scopes.empty())
744 : : {
745 : : vector<Dwarf_Die> other = getscopes(&scopes[0]);
746 : : assert(scopes.size() == other.size());
747 : : for (unsigned i = 0; i < scopes.size(); ++i)
748 : : assert(scopes[i].addr == other[i].addr);
749 : : }
750 : : #endif
751 : :
752 : 25 : return scopes;
753 : : }
754 : :
755 : :
756 : : Dwarf_Die*
757 : 0 : dwflpp::get_parent_scope(Dwarf_Die* die)
758 : : {
759 : : Dwarf_Die specification;
760 [ # # ][ # # ]: 0 : if (dwarf_attr_die(die, DW_AT_specification, &specification))
761 : 0 : die = &specification;
762 : :
763 [ # # ]: 0 : cu_die_parent_cache_t *parents = get_die_parents();
764 [ # # ]: 0 : cu_die_parent_cache_t::iterator it = parents->find(die->addr);
765 [ # # ][ # # ]: 0 : while (it != parents->end())
766 : : {
767 [ # # ]: 0 : Dwarf_Die* scope = &it->second;
768 [ # # ][ # # ]: 0 : switch (dwarf_tag (scope))
769 : : {
770 : : case DW_TAG_namespace:
771 : : case DW_TAG_class_type:
772 : : case DW_TAG_structure_type:
773 : 0 : return scope;
774 : :
775 : : default:
776 : 0 : break;
777 : : }
778 [ # # ]: 0 : it = parents->find(scope->addr);
779 : : }
780 : 0 : return NULL;
781 : : }
782 : :
783 : : static const char*
784 : 80567326 : cache_type_prefix(Dwarf_Die* type)
785 : : {
786 [ + + + + ]: 80567326 : switch (dwarf_tag(type))
787 : : {
788 : : case DW_TAG_enumeration_type:
789 : 4544356 : return "enum ";
790 : : case DW_TAG_structure_type:
791 : : case DW_TAG_class_type:
792 : : // treating struct/class as equals
793 : 49442489 : return "struct ";
794 : : case DW_TAG_union_type:
795 : 788072 : return "union ";
796 : : }
797 : 80567326 : return "";
798 : : }
799 : :
800 : : /* GCC might generate a struct/class without DW_AT_declaration,
801 : : but that only contains members which have DW_AT_declaration
802 : : set. We aren't interested in those. PR14434 (GCC bug #54181). */
803 : : static bool
804 : 80567192 : has_only_decl_members (Dwarf_Die *die)
805 : : {
806 : : Dwarf_Die child, import;
807 [ + - ][ + + ]: 80567192 : if (dwarf_child(die, &child) != 0)
808 : 26297425 : return false; /* no members */
809 : :
810 [ + + ]: 904 : do
811 : : {
812 [ + - ][ + + ]: 54270532 : if (! dwarf_hasattr(&child, DW_AT_declaration))
813 : 54269625 : return false; /* real member found. */
814 [ + - ]: 907 : int tag = dwarf_tag(&child);
815 [ + - ][ + - ]: 911 : if ((tag == DW_TAG_namespace
[ + + ][ + + ]
[ + + ]
816 : : || tag == DW_TAG_structure_type
817 : : || tag == DW_TAG_class_type)
818 [ + - ]: 4 : && ! has_only_decl_members (&child))
819 : 3 : return false; /* real grand child member found. */
820 : :
821 : : // Unlikely to ever happen, but if there is an imported unit
822 : : // then check its children as if they are children of this DIE.
823 [ - + ][ # # ]: 904 : if (tag == DW_TAG_imported_unit
[ # # ][ - + ]
824 [ # # ]: 0 : && dwarf_attr_die(&child, DW_AT_import, &import)
825 [ # # ]: 0 : && ! has_only_decl_members (&import))
826 : 0 : return false;
827 : : }
828 [ + - ]: 904 : while (dwarf_siblingof(&child, &child) == 0);
829 : :
830 : 80567192 : return true; /* Tried all children and grandchildren. */
831 : : }
832 : :
833 : : int
834 : 108163870 : dwflpp::global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types,
835 : : const string& prefix, void *arg)
836 : : {
837 : 108163870 : cu_type_cache_t *cache = static_cast<cu_type_cache_t*>(arg);
838 : 108163870 : const char *name = dwarf_diename(die);
839 : :
840 [ + + ]: 188731058 : if (!name || dwarf_hasattr(die, DW_AT_declaration)
[ + + + + ]
[ + + ]
841 : 80567188 : || has_only_decl_members(die))
842 : 27596820 : return DWARF_CB_OK;
843 : :
844 : 80567050 : int tag = dwarf_tag(die);
845 [ + + ][ + + ]: 80567050 : if (has_inner_types && (tag == DW_TAG_namespace
[ + + ][ + + ]
846 : : || tag == DW_TAG_structure_type
847 : : || tag == DW_TAG_class_type))
848 : : iterate_over_types(die, has_inner_types, prefix + name + "::",
849 [ + - ][ + - ]: 10089 : global_alias_caching_callback, arg);
[ + - ]
850 : :
851 [ + + ]: 80567050 : if (tag != DW_TAG_namespace)
852 : : {
853 [ + - ][ + - ]: 80566856 : string type_name = prefix + cache_type_prefix(die) + name;
[ + - ][ + - ]
854 [ + - ][ + - ]: 80566856 : if (cache->find(type_name) == cache->end())
[ + - ]
855 [ + - ][ + - ]: 80566856 : (*cache)[type_name] = *die;
856 : : }
857 : :
858 : 108163870 : return DWARF_CB_OK;
859 : : }
860 : :
861 : : int
862 : 13262408 : dwflpp::global_alias_caching_callback_cus(Dwarf_Die *die, void *arg)
863 : : {
864 : : mod_cu_type_cache_t *global_alias_cache;
865 : 13262408 : global_alias_cache = &static_cast<dwflpp *>(arg)->global_alias_cache;
866 : :
867 : 13262408 : cu_type_cache_t *v = (*global_alias_cache)[die->addr];
868 [ + + ]: 13262408 : if (v != 0)
869 : 12986105 : return DWARF_CB_OK;
870 : :
871 [ + - ][ + - ]: 276303 : v = new cu_type_cache_t;
872 : 276303 : (*global_alias_cache)[die->addr] = v;
873 : 276303 : iterate_over_globals(die, global_alias_caching_callback, v);
874 : :
875 : 13262408 : return DWARF_CB_OK;
876 : : }
877 : :
878 : : Dwarf_Die *
879 : 20477 : dwflpp::declaration_resolve_other_cus(const string& name)
880 : : {
881 : 20477 : iterate_over_cus(global_alias_caching_callback_cus, this, true);
882 [ + - ][ + - ]: 17327320 : for (mod_cu_type_cache_t::iterator i = global_alias_cache.begin();
[ + + ]
883 [ + - ]: 8663660 : i != global_alias_cache.end(); ++i)
884 : : {
885 : 8652111 : cu_type_cache_t *v = (*i).second;
886 [ + - ][ + - ]: 8652111 : if (v->find(name) != v->end())
[ + + ]
887 [ + - ]: 8928 : return & ((*v)[name]);
888 : : }
889 : :
890 : 20477 : return NULL;
891 : : }
892 : :
893 : : Dwarf_Die *
894 : 470 : dwflpp::declaration_resolve(const string& name)
895 : : {
896 : 470 : cu_type_cache_t *v = global_alias_cache[cu->addr];
897 [ + + ]: 470 : if (v == 0) // need to build the cache, just once per encountered module/cu
898 : : {
899 [ + - ][ + - ]: 15 : v = new cu_type_cache_t;
900 : 15 : global_alias_cache[cu->addr] = v;
901 : 15 : iterate_over_globals(cu, global_alias_caching_callback, v);
902 [ - + ]: 15 : if (sess.verbose > 4)
903 [ # # ][ # # ]: 0 : clog << _F("global alias cache %s:%s size %zu", module_name.c_str(),
[ # # ][ # # ]
904 [ # # ]: 0 : cu_name().c_str(), v->size()) << endl;
905 : : }
906 : :
907 : : // XXX: it may be desirable to search other modules' declarations
908 : : // too, in case a module/shared-library processes a
909 : : // forward-declared pointer type only, where the actual definition
910 : : // may only be in vmlinux or the application.
911 : :
912 [ + - ][ + - ]: 470 : if (v->find(name) == v->end())
913 : 470 : return declaration_resolve_other_cus(name);
914 : :
915 : 470 : return & ((*v)[name]);
916 : : }
917 : :
918 : : Dwarf_Die *
919 : 470 : dwflpp::declaration_resolve(Dwarf_Die *type)
920 : : {
921 [ + - ]: 470 : const char* name = dwarf_diename(type);
922 [ - + ]: 470 : if (!name)
923 : 0 : return NULL;
924 : :
925 [ + - ][ + - ]: 470 : string type_name = cache_type_prefix(type) + string(name);
[ + - ][ + - ]
926 [ + - ][ + - ]: 470 : return declaration_resolve(type_name);
927 : : }
928 : :
929 : :
930 : : int
931 : 36186619 : dwflpp::cu_function_caching_callback (Dwarf_Die* func, void *arg)
932 : : {
933 : 36186619 : cu_function_cache_t* v = static_cast<cu_function_cache_t*>(arg);
934 : 36186619 : const char *name = dwarf_diename(func);
935 [ - + ]: 36186619 : if (!name)
936 : 0 : return DWARF_CB_OK;
937 : :
938 [ + - ][ + - ]: 36186619 : v->insert(make_pair(string(name), *func));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
939 : 36186619 : return DWARF_CB_OK;
940 : : }
941 : :
942 : :
943 : : int
944 : 484963 : dwflpp::mod_function_caching_callback (Dwarf_Die* cu, void *arg)
945 : : {
946 : 484963 : dwarf_getfuncs (cu, cu_function_caching_callback, arg, 0);
947 : 484963 : return DWARF_CB_OK;
948 : : }
949 : :
950 : :
951 : : int
952 : 97912 : dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * q),
953 : : base_query * q, const string& function)
954 : : {
955 : 97912 : int rc = DWARF_CB_OK;
956 [ - + ]: 97912 : assert (module);
957 [ - + ]: 97912 : assert (cu);
958 : :
959 [ + - ]: 97912 : cu_function_cache_t *v = cu_function_cache[cu->addr];
960 [ + + ]: 97912 : if (v == 0)
961 : : {
962 [ + - ][ + - ]: 44199 : v = new cu_function_cache_t;
963 [ + - ]: 44199 : cu_function_cache[cu->addr] = v;
964 [ + - ]: 44199 : dwarf_getfuncs (cu, cu_function_caching_callback, v, 0);
965 [ - + ]: 44199 : if (sess.verbose > 4)
966 [ # # ][ # # ]: 0 : clog << _F("function cache %s:%s size %zu", module_name.c_str(),
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
967 [ # # ]: 0 : cu_name().c_str(), v->size()) << endl;
968 [ + - ]: 44199 : mod_info->update_symtab(v);
969 : : }
970 : :
971 [ + - ]: 97912 : cu_function_cache_t::iterator it;
972 [ + - ]: 97912 : cu_function_cache_range_t range = v->equal_range(function);
973 [ + + ]: 97912 : if (range.first != range.second)
974 : : {
975 [ + - ][ + + ]: 60843 : for (it = range.first; it != range.second; ++it)
976 : : {
977 [ + - ]: 30545 : Dwarf_Die& die = it->second;
978 [ - + ]: 30545 : if (sess.verbose > 4)
979 [ # # ][ # # ]: 0 : clog << _F("function cache %s:%s hit %s", module_name.c_str(),
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
980 [ # # ]: 0 : cu_name().c_str(), function.c_str()) << endl;
981 [ + - ]: 30545 : rc = (*callback)(& die, q);
982 [ - + ]: 30545 : if (rc != DWARF_CB_OK) break;
983 : : }
984 : : }
985 [ + - ][ - + ]: 67614 : else if (startswith(function, "_Z"))
986 : : {
987 : : // C++ names are mangled starting with a "_Z" prefix. Most of the time
988 : : // we can discover the mangled name from a die's MIPS_linkage_name
989 : : // attribute, so we read that to match against the user's function
990 : : // pattern. Note that this isn't perfect, as not all will have that
991 : : // attribute (notably ctors and dtors), but we do what we can...
992 [ # # ][ # # ]: 0 : for (it = v->begin(); it != v->end(); ++it)
[ # # ][ # # ]
993 : : {
994 [ # # ]: 0 : if (pending_interrupts) return DWARF_CB_ABORT;
995 [ # # ]: 0 : Dwarf_Die& die = it->second;
996 : 0 : const char* linkage_name = NULL;
997 [ # # ][ # # ]: 0 : if ((linkage_name = dwarf_linkage_name (&die))
[ # # ][ # # ]
998 [ # # ][ # # ]: 0 : && function_name_matches_pattern (linkage_name, function))
[ # # ][ # # ]
[ # # ]
[ # # # # ]
999 : : {
1000 [ # # ]: 0 : if (sess.verbose > 4)
1001 [ # # ][ # # ]: 0 : clog << _F("function cache %s:%s match %s vs %s", module_name.c_str(),
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1002 [ # # ]: 0 : cu_name().c_str(), linkage_name, function.c_str()) << endl;
1003 : :
1004 [ # # ]: 0 : rc = (*callback)(& die, q);
1005 [ # # ]: 0 : if (rc != DWARF_CB_OK) break;
1006 : : }
1007 : : }
1008 : : }
1009 [ + - ][ + + ]: 67614 : else if (name_has_wildcard (function))
1010 : : {
1011 [ + - ][ + - ]: 2815093 : for (it = v->begin(); it != v->end(); ++it)
[ + - ][ + + ]
1012 : : {
1013 [ - + ]: 2774005 : if (pending_interrupts) return DWARF_CB_ABORT;
1014 [ + - ]: 2774005 : const string& func_name = it->first;
1015 [ + - ]: 2774005 : Dwarf_Die& die = it->second;
1016 [ + - ][ + + ]: 2774005 : if (function_name_matches_pattern (func_name, function))
1017 : : {
1018 [ - + ]: 641744 : if (sess.verbose > 4)
1019 [ # # ][ # # ]: 0 : clog << _F("function cache %s:%s match %s vs %s", module_name.c_str(),
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1020 [ # # ]: 0 : cu_name().c_str(), func_name.c_str(), function.c_str()) << endl;
1021 : :
1022 [ + - ]: 641744 : rc = (*callback)(& die, q);
1023 [ - + ]: 641744 : if (rc != DWARF_CB_OK) break;
1024 : : }
1025 : : }
1026 : : }
1027 : : else // not a linkage name or wildcard and no match in this CU
1028 : : {
1029 : : // do nothing
1030 : : }
1031 : 97912 : return rc;
1032 : : }
1033 : :
1034 : :
1035 : : int
1036 : 45652 : dwflpp::iterate_single_function (int (* callback)(Dwarf_Die * func, base_query * q),
1037 : : base_query * q, const string& function)
1038 : : {
1039 : 45652 : int rc = DWARF_CB_OK;
1040 [ - + ]: 45652 : assert (module);
1041 : :
1042 [ + - ]: 45652 : get_module_dwarf(false);
1043 [ - + ]: 45652 : if (!module_dwarf)
1044 : 0 : return rc;
1045 : :
1046 [ + - ]: 45652 : cu_function_cache_t *v = mod_function_cache[module_dwarf];
1047 [ + + ]: 45652 : if (v == 0)
1048 : : {
1049 [ + - ][ + - ]: 374 : v = new cu_function_cache_t;
1050 [ + - ]: 374 : mod_function_cache[module_dwarf] = v;
1051 [ + - ]: 374 : iterate_over_cus (mod_function_caching_callback, v, false);
1052 [ - + ]: 374 : if (sess.verbose > 4)
1053 [ # # ][ # # ]: 0 : clog << _F("module function cache %s size %zu", module_name.c_str(),
[ # # ][ # # ]
1054 [ # # ]: 0 : v->size()) << endl;
1055 [ + - ]: 374 : mod_info->update_symtab(v);
1056 : : }
1057 : :
1058 [ + - ]: 45652 : cu_function_cache_t::iterator it;
1059 [ + - ]: 45652 : cu_function_cache_range_t range = v->equal_range(function);
1060 [ + + ]: 45652 : if (range.first != range.second)
1061 : : {
1062 [ + - ][ + + ]: 71777 : for (it = range.first; it != range.second; ++it)
1063 : : {
1064 : : Dwarf_Die cu_mem;
1065 [ + - ]: 42049 : Dwarf_Die& die = it->second;
1066 [ - + ]: 42049 : if (sess.verbose > 4)
1067 [ # # ][ # # ]: 0 : clog << _F("module function cache %s hit %s", module_name.c_str(),
[ # # ][ # # ]
[ # # ]
1068 [ # # ]: 0 : function.c_str()) << endl;
1069 : :
1070 : : // since we're iterating out of cu-context, we need each focus
1071 [ + - ][ + - ]: 42049 : focus_on_cu(dwarf_diecu(&die, &cu_mem, NULL, NULL));
1072 : :
1073 [ + - ]: 42049 : rc = (*callback)(& die, q);
1074 [ + - ]: 42049 : if (rc != DWARF_CB_OK) break;
1075 : : }
1076 : : }
1077 : :
1078 : : // undo the focus_on_cu
1079 : 45652 : this->cu = NULL;
1080 [ + - ]: 45652 : this->function_name.clear();
1081 : 45652 : this->function = NULL;
1082 : :
1083 : 45652 : return rc;
1084 : : }
1085 : :
1086 : :
1087 : : /* This basically only goes one level down from the compile unit so it
1088 : : * only picks up top level stuff (i.e. nothing in a lower scope) */
1089 : : int
1090 : 276318 : dwflpp::iterate_over_globals (Dwarf_Die *cu_die,
1091 : : int (* callback)(Dwarf_Die *, bool,
1092 : : const string&, void *),
1093 : : void * data)
1094 : : {
1095 [ - + ]: 276318 : assert (cu_die);
1096 : 276319 : assert (dwarf_tag(cu_die) == DW_TAG_compile_unit
1097 : : || dwarf_tag(cu_die) == DW_TAG_type_unit
1098 [ + + - + : 276319 : || dwarf_tag(cu_die) == DW_TAG_partial_unit);
# # ]
1099 : :
1100 : : // Ignore partial_unit, if they get imported by a real unit, then
1101 : : // iterate_over_types will traverse them.
1102 [ - + ]: 276318 : if (dwarf_tag(cu_die) == DW_TAG_partial_unit)
1103 : 0 : return DWARF_CB_OK;
1104 : :
1105 : : // If this is C++, recurse for any inner types
1106 : 276318 : bool has_inner_types = dwarf_srclang(cu_die) == DW_LANG_C_plus_plus;
1107 : :
1108 [ + - ][ + - ]: 276318 : return iterate_over_types(cu_die, has_inner_types, "", callback, data);
[ + - ]
1109 : : }
1110 : :
1111 : :
1112 : : int
1113 : 286407 : dwflpp::iterate_over_types (Dwarf_Die *top_die,
1114 : : bool has_inner_types,
1115 : : const string& prefix,
1116 : : int (* callback)(Dwarf_Die *, bool,
1117 : : const string&, void *),
1118 : : void * data)
1119 : : {
1120 : 286407 : int rc = DWARF_CB_OK;
1121 : : Dwarf_Die die, import;
1122 : :
1123 [ - + ]: 286407 : assert (top_die);
1124 : :
1125 [ + - ][ + + ]: 286407 : if (dwarf_child(top_die, &die) != 0)
1126 : 10964 : return rc;
1127 : :
1128 [ + - ][ + + ]: 635857122 : do
[ + + ]
1129 : : /* We're only currently looking for named types,
1130 : : * although other types of declarations exist */
1131 [ + - ]: 317928561 : switch (dwarf_tag(&die))
[ + - + ]
1132 : : {
1133 : : case DW_TAG_base_type:
1134 : : case DW_TAG_enumeration_type:
1135 : : case DW_TAG_structure_type:
1136 : : case DW_TAG_class_type:
1137 : : case DW_TAG_typedef:
1138 : : case DW_TAG_union_type:
1139 : : case DW_TAG_namespace:
1140 [ + - ]: 108163870 : rc = (*callback)(&die, has_inner_types, prefix, data);
1141 : 108163870 : break;
1142 : :
1143 : : case DW_TAG_imported_unit:
1144 : : // Follow the imported_unit and iterate over its contents
1145 : : // (either a partial_unit or a full compile_unit), all its
1146 : : // children should be treated as if they appear in this place.
1147 [ # # ][ # # ]: 0 : if (dwarf_attr_die(&die, DW_AT_import, &import))
1148 : : rc = iterate_over_types(&import, has_inner_types, prefix,
1149 [ # # ]: 0 : callback, data);
1150 : 0 : break;
1151 : : }
1152 [ + - ]: 317928561 : while (rc == DWARF_CB_OK && dwarf_siblingof(&die, &die) == 0);
1153 : :
1154 : 286407 : return rc;
1155 : : }
1156 : :
1157 : :
1158 : : /* For each notes section in the current module call 'callback', use
1159 : : * 'data' for the notes buffer and pass 'object' back in case
1160 : : * 'callback' is a method */
1161 : :
1162 : : int
1163 : 3 : dwflpp::iterate_over_notes (void *object, void (*callback)(void *object, int type, const char *data, size_t len))
1164 : : {
1165 : : Dwarf_Addr bias;
1166 : : // Note we really want the actual elf file, not the dwarf .debug file.
1167 : : // Older binutils had a bug where they mangled the SHT_NOTE type during
1168 : : // --keep-debug.
1169 [ + - ]: 3 : Elf* elf = dwfl_module_getelf (module, &bias);
1170 : : size_t shstrndx;
1171 [ + - ][ - + ]: 3 : if (elf_getshdrstrndx (elf, &shstrndx))
1172 [ # # ]: 0 : return elf_errno();
1173 : :
1174 : 3 : Elf_Scn *scn = NULL;
1175 : :
1176 [ + - ]: 3 : vector<Dwarf_Die> notes;
1177 : :
1178 [ + - ][ + + ]: 126 : while ((scn = elf_nextscn (elf, scn)) != NULL)
1179 : : {
1180 : : GElf_Shdr shdr;
1181 [ + - ][ - + ]: 123 : if (gelf_getshdr (scn, &shdr) == NULL)
1182 : 0 : continue;
1183 [ + + ]: 123 : switch (shdr.sh_type)
1184 : : {
1185 : : case SHT_NOTE:
1186 [ + + ]: 9 : if (!(shdr.sh_flags & SHF_ALLOC))
1187 : : {
1188 [ + - ]: 3 : Elf_Data *data = elf_getdata (scn, NULL);
1189 : : size_t next;
1190 : : GElf_Nhdr nhdr;
1191 : : size_t name_off;
1192 : : size_t desc_off;
1193 [ + - ][ + + ]: 75 : for (size_t offset = 0;
1194 : : (next = gelf_getnote (data, offset, &nhdr, &name_off, &desc_off)) > 0;
1195 : : offset = next)
1196 [ + - ]: 72 : (*callback) (object, nhdr.n_type, (const char*)((long)(data->d_buf) + (long)desc_off), nhdr.n_descsz);
1197 : : }
1198 : 123 : break;
1199 : : }
1200 : : }
1201 [ + - ]: 3 : return 0;
1202 : : }
1203 : :
1204 : :
1205 : : /* For each entry in the .dynamic section in the current module call 'callback'
1206 : : * returning 'object' in case 'callback' is a method */
1207 : :
1208 : : void
1209 : 2 : dwflpp::iterate_over_libraries (void (*callback)(void *object, const char *arg), void *q)
1210 : : {
1211 [ + - ]: 2 : std::set<std::string> added;
1212 [ + - ]: 2 : string interpreter;
1213 : :
1214 [ + - ][ - + ]: 2 : assert (this->module_name.length() != 0);
1215 : :
1216 : : Dwarf_Addr bias;
1217 : : // We cannot use this: dwarf_getelf (dwfl_module_getdwarf (module, &bias))
1218 [ + - ]: 2 : Elf *elf = dwfl_module_getelf (module, &bias);
1219 : : // elf_getphdrnum (elf, &phnum) is not available in all versions of elfutils
1220 : : // needs libelf from elfutils 0.144+
1221 : 6 : for (int i = 0; ; i++)
1222 : : {
1223 : : GElf_Phdr mem;
1224 : : GElf_Phdr *phdr;
1225 [ + - ]: 6 : phdr = gelf_getphdr (elf, i, &mem);
1226 [ + - ]: 6 : if (phdr == NULL)
1227 : : break;
1228 [ + + ]: 6 : if (phdr->p_type == PT_INTERP)
1229 : : {
1230 : : size_t maxsize;
1231 [ + - ]: 2 : char *filedata = elf_rawfile (elf, &maxsize);
1232 : :
1233 [ + - ][ + - ]: 2 : if (filedata != NULL && phdr->p_offset < maxsize)
1234 [ + - ]: 2 : interpreter = (char*) (filedata + phdr->p_offset);
1235 : : break;
1236 : : }
1237 : : }
1238 : :
1239 [ + - ][ - + ]: 2 : if (interpreter.length() == 0)
1240 : : return;
1241 : : // If it gets cumbersome to maintain this whitelist, we could just check for
1242 : : // startswith("/lib/ld") || startswith("/lib64/ld"), and trust that no admin
1243 : : // would install untrustworthy loaders in those paths.
1244 : : // See also http://sourceware.org/git/?p=glibc.git;a=blob;f=shlib-versions;hb=HEAD
1245 [ + - ][ + - ]: 18 : if (interpreter != "/lib/ld.so.1" // s390, ppc
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
1246 [ + - ]: 2 : && interpreter != "/lib/ld64.so.1" // s390x, ppc64
1247 [ + - ]: 2 : && interpreter != "/lib64/ld64.so.1"
1248 [ + - ]: 2 : && interpreter != "/lib/ld-linux-ia64.so.2" // ia64
1249 [ + - ]: 2 : && interpreter != "/emul/ia32-linux/lib/ld-linux.so.2"
1250 [ + - ]: 2 : && interpreter != "/lib64/ld-linux-x86-64.so.2" // x8664
1251 [ + - ]: 2 : && interpreter != "/lib/ld-linux.so.2" // x86
1252 [ + - ]: 2 : && interpreter != "/lib/ld-linux.so.3" // arm
1253 [ + - ]: 2 : && interpreter != "/lib/ld-linux-armhf.so.3" // arm
1254 : : )
1255 : : {
1256 : 0 : sess.print_warning (_F("module %s --ldd skipped: unsupported interpreter: %s",
1257 [ # # ][ # # ]: 0 : module_name.c_str(), interpreter.c_str()));
[ # # ][ # # ]
[ # # ]
1258 : : return;
1259 : : }
1260 : :
1261 [ + - ]: 2 : vector<string> ldd_command;
1262 [ + - ][ + - ]: 2 : ldd_command.push_back("/usr/bin/env");
[ + - ]
1263 [ + - ][ + - ]: 2 : ldd_command.push_back("LD_TRACE_LOADED_OBJECTS=1");
[ + - ]
1264 [ + - ][ + - ]: 2 : ldd_command.push_back("LD_WARN=yes");
[ + - ]
1265 [ + - ][ + - ]: 2 : ldd_command.push_back("LD_BIND_NOW=yes");
[ + - ]
1266 [ + - ]: 2 : ldd_command.push_back(interpreter);
1267 [ + - ]: 2 : ldd_command.push_back(module_name);
1268 : :
1269 : : FILE *fp;
1270 : : int child_fd;
1271 [ + - ]: 2 : pid_t child = stap_spawn_piped(sess.verbose, ldd_command, NULL, &child_fd);
1272 [ + - ][ - + ]: 2 : if (child <= 0 || !(fp = fdopen(child_fd, "r")))
[ - + ]
1273 [ # # ][ # # ]: 0 : clog << _F("library iteration on %s failed: %s",
[ # # ][ # # ]
1274 [ # # ]: 0 : module_name.c_str(), strerror(errno)) << endl;
1275 : : else
1276 : : {
1277 : 22 : while (1) // this parsing loop borrowed from add_unwindsym_ldd
1278 : : {
1279 : : char linebuf[256];
1280 : 24 : char *soname = 0;
1281 : 24 : char *shlib = 0;
1282 : 24 : unsigned long int addr = 0;
1283 : :
1284 [ + - ]: 24 : char *line = fgets (linebuf, 256, fp);
1285 [ + + ]: 24 : if (line == 0) break; // EOF or error
1286 : :
1287 : : #if __GLIBC__ >2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)
1288 : : #define MS_FMT "%ms"
1289 : : #else
1290 : : #define MS_FMT "%as"
1291 : : #endif
1292 : : // Try soname => shlib (0xaddr)
1293 : : int nf = sscanf (line, MS_FMT " => " MS_FMT " (0x%lx)",
1294 : 22 : &soname, &shlib, &addr);
1295 [ + + ][ - + ]: 22 : if (nf != 3 || shlib[0] != '/')
1296 : : {
1297 : : // Try shlib (0xaddr)
1298 : 2 : nf = sscanf (line, " " MS_FMT " (0x%lx)", &shlib, &addr);
1299 [ + - ][ - + ]: 2 : if (nf != 2 || shlib[0] != '/')
1300 : 0 : continue; // fewer than expected fields, or bad shlib.
1301 : : }
1302 : :
1303 [ + - ][ + - ]: 22 : if (added.find (shlib) == added.end())
[ + - ][ + - ]
[ + - ]
1304 : : {
1305 [ + + ]: 22 : if (sess.verbose > 2)
1306 : : {
1307 [ + - ][ + - ]: 11 : clog << _F("Added -d '%s", shlib);
[ + - ]
1308 [ + + ]: 11 : if (nf == 3)
1309 [ + - ][ + - ]: 10 : clog << _F("' due to '%s'", soname);
[ + - ]
1310 : : else
1311 [ + - ]: 1 : clog << "'";
1312 [ + - ]: 11 : clog << endl;
1313 : : }
1314 [ + - ][ + - ]: 22 : added.insert (shlib);
[ + - ]
1315 : : }
1316 : :
1317 : 22 : free (soname);
1318 : 22 : free (shlib);
1319 : : }
1320 [ + - ][ + - ]: 2 : if ((fclose(fp) || stap_waitpid(sess.verbose, child)))
[ + - ][ - + ]
[ - + ]
1321 [ # # ][ # # ]: 0 : sess.print_warning("failed to read libraries from " + module_name + ": " + strerror(errno));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1322 : : }
1323 : :
1324 [ + - ][ + + ]: 48 : for (std::set<std::string>::iterator it = added.begin();
1325 [ + - ]: 24 : it != added.end();
1326 : : it++)
1327 : : {
1328 [ + - ]: 22 : string modname = *it;
1329 [ + - ][ + - ]: 22 : (callback) (q, modname.c_str());
1330 [ + - ][ + - ]: 24 : }
[ + - ][ - + ]
[ + - ][ + - ]
1331 : : }
1332 : :
1333 : :
1334 : : /* For each plt section in the current module call 'callback', pass the plt entry
1335 : : * 'address' and 'name' back, and pass 'object' back in case 'callback' is a method */
1336 : :
1337 : : int
1338 : 13 : dwflpp::iterate_over_plt (void *object, void (*callback)(void *object, const char *name, size_t addr))
1339 : : {
1340 : : Dwarf_Addr load_addr;
1341 : : // Note we really want the actual elf file, not the dwarf .debug file.
1342 [ + - ]: 13 : Elf* elf = dwfl_module_getelf (module, &load_addr);
1343 : : size_t shstrndx;
1344 [ + - ][ - + ]: 13 : assert (elf_getshdrstrndx (elf, &shstrndx) >= 0);
1345 : :
1346 : : // Get the load address
1347 : 37 : for (int i = 0; ; i++)
1348 : : {
1349 : : GElf_Phdr mem;
1350 : : GElf_Phdr *phdr;
1351 [ + - ]: 37 : phdr = gelf_getphdr (elf, i, &mem);
1352 [ + - ]: 37 : if (phdr == NULL)
1353 : : break;
1354 [ + + ]: 37 : if (phdr->p_type == PT_LOAD)
1355 : : {
1356 : 13 : load_addr = phdr->p_vaddr;
1357 : : break;
1358 : : }
1359 : : }
1360 : :
1361 : : // Get the plt section header
1362 : 13 : Elf_Scn *scn = NULL;
1363 : 13 : GElf_Shdr *plt_shdr = NULL;
1364 : : GElf_Shdr plt_shdr_mem;
1365 [ + - ][ + - ]: 145 : while ((scn = elf_nextscn (elf, scn)))
1366 : : {
1367 [ + - ]: 145 : plt_shdr = gelf_getshdr (scn, &plt_shdr_mem);
1368 [ - + ]: 145 : assert (plt_shdr != NULL);
1369 [ + - ][ + + ]: 145 : if (strcmp (elf_strptr (elf, shstrndx, plt_shdr->sh_name), ".plt") == 0)
1370 : 13 : break;
1371 : : }
1372 : :
1373 : : // Layout of the plt section
1374 : : int plt0_entry_size;
1375 : : int plt_entry_size;
1376 : : GElf_Ehdr ehdr_mem;
1377 [ + - ]: 13 : GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
1378 [ - - + ]: 13 : switch (em->e_machine)
1379 : : {
1380 : 0 : case EM_386: plt0_entry_size = 16; plt_entry_size = 16; break;
1381 : 0 : case EM_X86_64: plt0_entry_size = 16; plt_entry_size = 16; break;
1382 : : case EM_PPC64:
1383 : : case EM_S390:
1384 : : case EM_PPC:
1385 : : default:
1386 [ + - ][ + - ]: 13 : throw semantic_error(".plt is not supported on this architecture");
1387 : : }
1388 : :
1389 : 0 : scn = NULL;
1390 [ # # ][ # # ]: 0 : while ((scn = elf_nextscn (elf, scn)))
1391 : : {
1392 : : GElf_Shdr shdr_mem;
1393 [ # # ]: 0 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
1394 : 0 : bool have_rela = false;
1395 : 0 : bool have_rel = false;
1396 : :
1397 [ # # ]: 0 : if (shdr == NULL)
1398 : 0 : continue;
1399 [ # # ]: 0 : assert (shdr != NULL);
1400 : :
1401 [ # # ][ # # ]: 0 : if ((have_rela = (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".rela.plt") == 0))
[ # # ][ # # ]
1402 [ # # ]: 0 : || (have_rel = (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".rel.plt") == 0)))
1403 : : {
1404 : : /* Get the data of the section. */
1405 [ # # ]: 0 : Elf_Data *data = elf_getdata (scn, NULL);
1406 [ # # ]: 0 : assert (data != NULL);
1407 : : /* Get the symbol table information. */
1408 [ # # ]: 0 : Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
1409 : : GElf_Shdr symshdr_mem;
1410 [ # # ]: 0 : GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
1411 [ # # ]: 0 : assert (symshdr != NULL);
1412 [ # # ]: 0 : Elf_Data *symdata = elf_getdata (symscn, NULL);
1413 [ # # ]: 0 : assert (symdata != NULL);
1414 : :
1415 : 0 : unsigned int nsyms = shdr->sh_size / shdr->sh_entsize;
1416 : :
1417 [ # # ]: 0 : for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
1418 : : {
1419 : : GElf_Ehdr ehdr_mem;
1420 [ # # ]: 0 : GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
1421 [ # # ][ # # ]: 13 : if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); }
[ # # ][ # # ]
[ # # ]
1422 : :
1423 : : GElf_Rela relamem;
1424 : 0 : GElf_Rela *rela = NULL;
1425 : : GElf_Rel relmem;
1426 : 0 : GElf_Rel *rel = NULL;
1427 [ # # ]: 0 : if (have_rela)
1428 : : {
1429 [ # # ]: 0 : rela = gelf_getrela (data, cnt, &relamem);
1430 [ # # ]: 0 : assert (rela != NULL);
1431 : : }
1432 [ # # ]: 0 : else if (have_rel)
1433 : : {
1434 [ # # ]: 0 : rel = gelf_getrel (data, cnt, &relmem);
1435 [ # # ]: 0 : assert (rel != NULL);
1436 : : }
1437 : : GElf_Sym symmem;
1438 : : Elf32_Word xndx;
1439 : 0 : Elf_Data *xndxdata = NULL;
1440 : : GElf_Sym *sym =
1441 : : gelf_getsymshndx (symdata, xndxdata,
1442 : : GELF_R_SYM (have_rela ? rela->r_info : rel->r_info),
1443 [ # # ][ # # ]: 0 : &symmem, &xndx);
1444 [ # # ]: 0 : assert (sym != NULL);
1445 : 0 : Dwarf_Addr addr = plt_shdr->sh_offset + plt0_entry_size + cnt * plt_entry_size;
1446 : :
1447 [ # # ][ # # ]: 0 : if (elf_strptr (elf, symshdr->sh_link, sym->st_name))
1448 [ # # ][ # # ]: 0 : (*callback) (object, elf_strptr (elf, symshdr->sh_link, sym->st_name), addr + load_addr);
1449 : : }
1450 : : break; // while scn
1451 : : }
1452 : : }
1453 : 0 : return 0;
1454 : : }
1455 : :
1456 : :
1457 : : // This little test routine represents an unfortunate breakdown in
1458 : : // abstraction between dwflpp (putatively, a layer right on top of
1459 : : // elfutils), and dwarf_query (interpreting a systemtap probe point).
1460 : : // It arises because we sometimes try to fix up slightly-off
1461 : : // .statement() probes (something we find out in fairly low-level).
1462 : : //
1463 : : // An alternative would be to put some more intelligence into query_cu(),
1464 : : // and have it print additional suggestions after finding that
1465 : : // q->dw.iterate_over_srcfile_lines resulted in no new finished_results.
1466 : :
1467 : : bool
1468 : 2 : dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int lineno)
1469 : : {
1470 [ - + ]: 2 : if (lineno < 0)
1471 : 0 : return false;
1472 : :
1473 : 2 : Dwarf_Line **srcsp = NULL;
1474 : 2 : size_t nsrcs = 0;
1475 : :
1476 : : dwarf_assert ("dwarf_getsrc_file",
1477 : : dwarf_getsrc_file (module_dwarf,
1478 : : srcfile, lineno, 0,
1479 [ + - ][ + - ]: 2 : &srcsp, &nsrcs));
[ + - ][ + - ]
1480 : :
1481 [ - + ]: 2 : if (nsrcs != 1)
1482 : : {
1483 [ # # ]: 0 : if (sess.verbose>4)
1484 [ # # ][ # # ]: 0 : clog << _F("alternative line %d rejected: nsrcs=%zu", lineno, nsrcs) << endl;
[ # # ][ # # ]
1485 : 0 : return false;
1486 : : }
1487 : :
1488 : : // We also try to filter out lines that leave the selected
1489 : : // functions (if any).
1490 : :
1491 : 2 : dwarf_line_t line(srcsp[0]);
1492 [ + - ]: 2 : Dwarf_Addr addr = line.addr();
1493 : :
1494 [ + - ]: 2 : func_info_map_t *filtered_functions = get_filtered_functions(q);
1495 [ + - ][ + - ]: 4 : for (func_info_map_t::iterator i = filtered_functions->begin();
[ + - ]
1496 [ + - ]: 2 : i != filtered_functions->end(); ++i)
1497 : : {
1498 [ + - ][ + - ]: 2 : if (die_has_pc (i->die, addr))
1499 : : {
1500 [ - + ]: 2 : if (sess.verbose>4)
1501 [ # # ][ # # ]: 0 : clog << _F("alternative line %d accepted: fn=%s", lineno, i->name.c_str()) << endl;
[ # # ][ # # ]
[ # # ]
1502 : 2 : return true;
1503 : : }
1504 : : }
1505 : :
1506 [ # # ]: 0 : inline_instance_map_t *filtered_inlines = get_filtered_inlines(q);
1507 [ # # ][ # # ]: 0 : for (inline_instance_map_t::iterator i = filtered_inlines->begin();
[ # # ]
1508 [ # # ]: 0 : i != filtered_inlines->end(); ++i)
1509 : : {
1510 [ # # ][ # # ]: 0 : if (die_has_pc (i->die, addr))
1511 : : {
1512 [ # # ]: 0 : if (sess.verbose>4)
1513 [ # # ][ # # ]: 0 : clog << _F("alternative line %d accepted: ifn=%s", lineno, i->name.c_str()) << endl;
[ # # ][ # # ]
[ # # ]
1514 : 0 : return true;
1515 : : }
1516 : : }
1517 : :
1518 [ # # ]: 0 : if (sess.verbose>4)
1519 : : //TRANSLATORS: given line number leaves (is beyond) given function.
1520 [ # # ][ # # ]: 0 : clog << _F("alternative line %d rejected: leaves selected fns", lineno) << endl;
[ # # ][ # # ]
1521 : 2 : return false;
1522 : : }
1523 : :
1524 : :
1525 : : void
1526 : 277032 : dwflpp::iterate_over_srcfile_lines (char const * srcfile,
1527 : : int lines[2],
1528 : : bool need_single_match,
1529 : : enum line_t line_type,
1530 : : void (* callback) (const dwarf_line_t& line,
1531 : : void * arg),
1532 : : const std::string& func_pattern,
1533 : : void *data)
1534 : : {
1535 : 277032 : Dwarf_Line **srcsp = NULL;
1536 : 277032 : size_t nsrcs = 0;
1537 : 277032 : dwarf_query * q = static_cast<dwarf_query *>(data);
1538 : 277032 : int lineno = lines[0];
1539 : 277032 : auto_free_ref<Dwarf_Line**> free_srcsp(srcsp);
1540 : :
1541 [ + - ]: 277032 : get_module_dwarf();
1542 [ + + ]: 277032 : if (!this->function)
1543 : : return;
1544 : :
1545 [ + + ]: 266 : if (line_type == RELATIVE)
1546 : : {
1547 : : Dwarf_Addr addr;
1548 : : Dwarf_Line *line;
1549 : : int line_number;
1550 : :
1551 [ + - ]: 5 : die_entrypc(this->function, &addr);
1552 : :
1553 [ + - ]: 5 : if (addr != 0)
1554 : : {
1555 [ + - ]: 5 : line = dwarf_getsrc_die (this->cu, addr);
1556 [ + - ][ + - ]: 5 : dwarf_assert ("dwarf_getsrc_die", line == NULL);
[ + - ]
1557 [ + - ][ + - ]: 5 : dwarf_assert ("dwarf_lineno", dwarf_lineno (line, &line_number));
[ + - ][ + - ]
1558 : : }
1559 [ # # ][ # # ]: 0 : else if (dwarf_decl_line (this->function, &line_number) != 0)
1560 : : {
1561 : : // use DW_AT_decl_line as a fallback method
1562 : : Dwarf_Attribute type_attr;
1563 : : Dwarf_Word constant;
1564 [ # # ][ # # ]: 0 : if (dwarf_attr_integrate (this->function, DW_AT_decl_line, &type_attr))
1565 : : {
1566 [ # # ]: 0 : dwarf_formudata (&type_attr, &constant);
1567 : 0 : line_number = constant;
1568 : : }
1569 : : else
1570 : : return;
1571 : : }
1572 : 5 : lineno += line_number;
1573 : : }
1574 [ + + ]: 261 : else if (line_type == WILDCARD) {
1575 [ + - ][ - + ]: 246 : if (name_has_wildcard(func_pattern)) /* PR14774: look at whole file if function name is wildcard */
1576 : 0 : lineno = 0;
1577 : : else
1578 [ + - ]: 246 : function_line (&lineno);
1579 : : }
1580 [ - + ]: 15 : else if (line_type == RANGE) { /* correct lineno */
1581 : : int start_lineno;
1582 : :
1583 [ # # ][ # # ]: 0 : if (name_has_wildcard(func_pattern)) /* PR10294: wider range like statement("*@foo.c") */
1584 : 0 : start_lineno = lineno;
1585 : : else
1586 [ # # ]: 0 : function_line (&start_lineno);
1587 [ # # ]: 0 : lineno = lineno < start_lineno ? start_lineno : lineno;
1588 [ # # ]: 0 : if (lineno > lines[1]) { /* invalid line range */
1589 [ # # ]: 0 : stringstream advice;
1590 [ # # ][ # # ]: 0 : advice << _("Invalid line range (") << lines[0] << "-" << lines[1] << ")";
[ # # ][ # # ]
[ # # ]
1591 [ # # ]: 0 : if (start_lineno > lines[1])
1592 [ # # ][ # # ]: 0 : advice << _(", the end line number ") << lines[1] << " < " << start_lineno;
[ # # ][ # # ]
1593 [ # # ][ # # ]: 0 : throw semantic_error (advice.str());
1594 : : }
1595 : : }
1596 : :
1597 : :
1598 : 8586 : for (int l = lineno; ; l = l + 1)
1599 : : {
1600 [ + - ]: 8586 : set<int> lines_probed;
1601 [ + - ]: 8586 : pair<set<int>::iterator,bool> line_probed;
1602 : 8586 : int ret = 0;
1603 : :
1604 [ + - ]: 8586 : assert_no_interrupts();
1605 : :
1606 : 8586 : nsrcs = 0;
1607 : : ret = dwarf_getsrc_file (module_dwarf, srcfile, l, 0,
1608 [ + - ]: 8586 : &srcsp, &nsrcs);
1609 [ + + ]: 8586 : if (ret != 0) /* tolerate invalid line number */
1610 : : break;
1611 : :
1612 [ + + ][ - + ]: 8337 : if (line_type == WILDCARD || line_type == RANGE)
1613 : : {
1614 : : Dwarf_Addr line_addr;
1615 : :
1616 [ + - ]: 8320 : dwarf_lineno (srcsp [0], &lineno);
1617 : : /* Maybe lineno will exceed the input end */
1618 [ - + ][ # # ]: 8320 : if (line_type == RANGE && lineno > lines[1])
1619 : : break;
1620 [ + - ]: 8320 : line_probed = lines_probed.insert(lineno);
1621 [ + + ][ + - ]: 8320 : if (lineno != l || line_probed.second == false || nsrcs > 1)
[ + + ]
1622 : 7574 : continue;
1623 [ + - ]: 746 : dwarf_lineaddr (srcsp [0], &line_addr);
1624 [ + - ][ - + ]: 746 : if (!function_name_matches(func_pattern) && dwarf_haspc (function, line_addr) != 1)
[ # # ][ # # ]
[ + - ]
1625 : : break;
1626 : : }
1627 : :
1628 : : // NB: Formerly, we used to filter, because:
1629 : :
1630 : : // dwarf_getsrc_file gets one *near hits* for line numbers, not
1631 : : // exact matches. For example, an existing file but a nonexistent
1632 : : // line number will be rounded up to the next definition in that
1633 : : // file. This may be similar to the GDB breakpoint algorithm, but
1634 : : // we don't want to be so fuzzy in systemtap land. So we filter.
1635 : :
1636 : : // But we now see the error of our ways, and skip this filtering.
1637 : :
1638 : : // XXX: the code also fails to match e.g. inline function
1639 : : // definitions when the srcfile is a header file rather than the
1640 : : // CU name.
1641 : :
1642 : 763 : size_t remaining_nsrcs = nsrcs;
1643 : :
1644 [ + - ][ + + ]: 763 : if (need_single_match && remaining_nsrcs > 1)
1645 : : {
1646 : : // We wanted a single line record (a unique address for the
1647 : : // line) and we got a bunch of line records. We're going to
1648 : : // skip this probe (throw an exception) but before we throw
1649 : : // we're going to look around a bit to see if there's a low or
1650 : : // high line number nearby which *doesn't* have this problem,
1651 : : // so we can give the user some advice.
1652 : :
1653 : 1 : int lo_try = -1;
1654 : 1 : int hi_try = -1;
1655 [ + + ]: 6 : for (size_t i = 1; i < 6; ++i)
1656 : : {
1657 [ + + ][ + - ]: 5 : if (lo_try == -1 && has_single_line_record(q, srcfile, lineno - i))
[ + - ][ + + ]
1658 : 1 : lo_try = lineno - i;
1659 : :
1660 [ + + ][ + - ]: 5 : if (hi_try == -1 && has_single_line_record(q, srcfile, lineno + i))
[ + - ][ + + ]
1661 : 1 : hi_try = lineno + i;
1662 : : }
1663 : :
1664 [ + - ]: 1 : stringstream advice;
1665 [ + - ][ + - ]: 1 : advice << _F("multiple addresses for %s:%d [man error::dwarf]", srcfile, lineno);
[ + - ]
1666 [ - + ][ # # ]: 1 : if (lo_try > 0 || hi_try > 0)
1667 : : {
1668 : : //TRANSLATORS: Here we are trying to advise what source file
1669 : : //TRANSLATORS: to attempt.
1670 [ + - ]: 1 : advice << _(" (try ");
1671 [ + - ]: 1 : if (lo_try > 0)
1672 [ + - ][ + - ]: 1 : advice << srcfile << ":" << lo_try;
[ + - ]
1673 [ + - ][ + - ]: 1 : if (lo_try > 0 && hi_try > 0)
1674 [ + - ]: 1 : advice << _(" or ");
1675 [ + - ]: 1 : if (hi_try > 0)
1676 [ + - ][ + - ]: 1 : advice << srcfile << ":" << hi_try;
[ + - ]
1677 [ + - ]: 1 : advice << ")";
1678 : : }
1679 [ + - ][ + - ]: 1 : throw semantic_error (advice.str());
1680 : : }
1681 : :
1682 [ + + ]: 1524 : for (size_t i = 0; i < nsrcs; ++i)
1683 : : {
1684 [ + - ]: 762 : assert_no_interrupts();
1685 [ + - ]: 762 : if (srcsp [i]) // skip over mismatched lines
1686 [ + - ]: 762 : callback (dwarf_line_t(srcsp[i]), data);
1687 : : }
1688 : :
1689 [ + + ][ + + ]: 762 : if (line_type == ABSOLUTE || line_type == RELATIVE)
1690 : : break;
1691 [ - + ][ # # ]: 746 : else if (line_type == RANGE && l == lines[1])
1692 : : break;
1693 [ + - ]: 285352 : }
[ + + + ]
[ + + ]
1694 : : }
1695 : :
1696 : :
1697 : : void
1698 : 8 : dwflpp::iterate_over_labels (Dwarf_Die *begin_die,
1699 : : const string& sym,
1700 : : const string& function,
1701 : : dwarf_query *q,
1702 : : void (* callback)(const string &,
1703 : : const char *,
1704 : : const char *,
1705 : : int,
1706 : : Dwarf_Die *,
1707 : : Dwarf_Addr,
1708 : : dwarf_query *))
1709 : : {
1710 [ + - ]: 8 : get_module_dwarf();
1711 : :
1712 : : Dwarf_Die die, import;
1713 : : const char *name;
1714 [ + - ]: 8 : int res = dwarf_child (begin_die, &die);
1715 [ + - ]: 8 : if (res != 0)
1716 : 8 : return; // die without children, bail out.
1717 : :
1718 [ + + ]: 18 : do
1719 : : {
1720 [ + - ]: 18 : switch (dwarf_tag(&die))
[ + + - + ]
1721 : : {
1722 : : case DW_TAG_label:
1723 [ + - ]: 6 : name = dwarf_diename (&die);
1724 [ + - ][ + - ]: 30 : if (name &&
[ + - ][ + - ]
[ + - ]
1725 [ + - ]: 6 : (name == sym
1726 [ + - ]: 6 : || (name_has_wildcard(sym)
1727 [ + - ][ + - ]: 12 : && function_name_matches_pattern (name, sym))))
[ + - ][ + - ]
[ + - ]
[ # # # # ]
1728 : : {
1729 : : // Don't try to be smart. Just drop no addr labels.
1730 : : Dwarf_Addr stmt_addr;
1731 [ + - ][ + - ]: 6 : if (dwarf_lowpc (&die, &stmt_addr) == 0)
1732 : : {
1733 : : // Get the file/line number for this label
1734 : : int dline;
1735 [ + - ]: 6 : const char *file = dwarf_decl_file (&die);
1736 [ + - ]: 6 : dwarf_decl_line (&die, &dline);
1737 : :
1738 [ + - ]: 6 : vector<Dwarf_Die> scopes = getscopes_die(&die);
1739 [ + - ]: 6 : if (scopes.size() > 1)
1740 : : {
1741 : : Dwarf_Die scope;
1742 [ + - ][ - + ]: 6 : if (!inner_die_containing_pc(scopes[1], stmt_addr, scope))
1743 : : {
1744 [ # # ][ # # ]: 0 : sess.print_warning(_F("label '%s' at address %s (dieoffset: %s) is not "
[ # # ]
1745 : : "contained by its scope '%s' (dieoffset: %s) -- bad"
1746 : : " debuginfo? [man error::dwarf]", name, lex_cast_hex(stmt_addr).c_str(),
1747 : : lex_cast_hex(dwarf_dieoffset(&die)).c_str(),
1748 : : (dwarf_diename(&scope) ?: "<unknown>"),
1749 [ # # ][ # # ]: 0 : lex_cast_hex(dwarf_dieoffset(&scope)).c_str()));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1750 : : }
1751 : : callback(function, name, file, dline,
1752 [ + - ]: 6 : &scope, stmt_addr, q);
1753 [ + - ]: 6 : }
1754 : : }
1755 : : }
1756 : 6 : break;
1757 : :
1758 : : case DW_TAG_subprogram:
1759 : : case DW_TAG_inlined_subroutine:
1760 : : // Stay within our filtered function
1761 : 1 : break;
1762 : :
1763 : : case DW_TAG_imported_unit:
1764 : : // Iterate over the children of the imported unit as if they
1765 : : // were inserted in place.
1766 [ # # ][ # # ]: 0 : if (dwarf_attr_die(&die, DW_AT_import, &import))
1767 [ # # ]: 0 : iterate_over_labels (&import, sym, function, q, callback);
1768 : 0 : break;
1769 : :
1770 : : default:
1771 [ + - ][ + + ]: 11 : if (dwarf_haschildren (&die))
1772 [ + - ]: 2 : iterate_over_labels (&die, sym, function, q, callback);
1773 : 11 : break;
1774 : : }
1775 : : }
1776 [ + - ]: 18 : while (dwarf_siblingof (&die, &die) == 0);
1777 : : }
1778 : :
1779 : :
1780 : : void
1781 : 121885 : dwflpp::collect_srcfiles_matching (string const & pattern,
1782 : : set<string> & filtered_srcfiles)
1783 : : {
1784 [ - + ]: 121885 : assert (module);
1785 [ - + ]: 121885 : assert (cu);
1786 : :
1787 : : size_t nfiles;
1788 : : Dwarf_Files *srcfiles;
1789 : :
1790 : : // PR 5049: implicit * in front of given path pattern.
1791 : : // NB: fnmatch() is used without FNM_PATHNAME.
1792 [ + - ][ + - ]: 121885 : string prefixed_pattern = string("*/") + pattern;
[ + - ]
1793 : :
1794 : : dwarf_assert ("dwarf_getsrcfiles",
1795 [ + - ][ + - ]: 121885 : dwarf_getsrcfiles (cu, &srcfiles, &nfiles));
[ + - ][ + - ]
1796 : : {
1797 [ + + ]: 12067819 : for (size_t i = 0; i < nfiles; ++i)
1798 : : {
1799 [ + - ]: 11945934 : char const * fname = dwarf_filesrc (srcfiles, i, NULL, NULL);
1800 [ + - ][ + - ]: 23478485 : if (fnmatch (pattern.c_str(), fname, 0) == 0 ||
[ + + ][ + + ]
[ + + ]
1801 [ + - ][ + - ]: 11532551 : fnmatch (prefixed_pattern.c_str(), fname, 0) == 0)
1802 : : {
1803 [ + - ][ + - ]: 413429 : filtered_srcfiles.insert (fname);
[ + - ]
1804 [ - + ]: 413429 : if (sess.verbose>2)
1805 [ # # ][ # # ]: 0 : clog << _F("selected source file '%s'\n", fname);
[ # # ]
1806 : : }
1807 : : }
1808 [ + - ]: 121885 : }
1809 : 121885 : }
1810 : :
1811 : :
1812 : : void
1813 : 59 : dwflpp::resolve_prologue_endings (func_info_map_t & funcs)
1814 : : {
1815 : : // This heuristic attempts to pick the first address that has a
1816 : : // source line distinct from the function declaration's. In a
1817 : : // perfect world, this would be the first statement *past* the
1818 : : // prologue.
1819 : :
1820 [ - + ]: 59 : assert(module);
1821 [ - + ]: 59 : assert(cu);
1822 : :
1823 : 59 : size_t nlines = 0;
1824 : 59 : Dwarf_Lines *lines = NULL;
1825 : :
1826 : : /* trouble cases:
1827 : : malloc do_symlink in init/initramfs.c tail-recursive/tiny then no-prologue
1828 : : sys_get?id in kernel/timer.c no-prologue
1829 : : sys_exit_group tail-recursive
1830 : : {do_,}sys_open extra-long-prologue (gcc 3.4)
1831 : : cpu_to_logical_apicid NULL-decl_file
1832 : : */
1833 : :
1834 : : // Fetch all srcline records, sorted by address.
1835 : : dwarf_assert ("dwarf_getsrclines",
1836 [ + - ][ + - ]: 59 : dwarf_getsrclines(cu, &lines, &nlines));
[ + - ][ + - ]
1837 : : // XXX: free lines[] later, but how?
1838 : :
1839 [ + - ][ + - ]: 11670 : for(func_info_map_t::iterator it = funcs.begin(); it != funcs.end(); it++)
[ + - ][ + - ]
[ + + ]
1840 : : {
1841 : : #if 0 /* someday */
1842 : : Dwarf_Addr* bkpts = 0;
1843 : : int n = dwarf_entry_breakpoints (& it->die, & bkpts);
1844 : : // ...
1845 : : free (bkpts);
1846 : : #endif
1847 : :
1848 : 11611 : Dwarf_Addr entrypc = it->entrypc;
1849 : : Dwarf_Addr highpc; // NB: highpc is exclusive: [entrypc,highpc)
1850 : 11611 : dwfl_assert ("dwarf_highpc", dwarf_highpc (& it->die,
1851 [ + - + - ]: 23222 : & highpc));
[ + - ][ + - ]
1852 : :
1853 [ + + ]: 11611 : if (it->decl_file == 0) it->decl_file = "";
1854 : :
1855 : 11611 : unsigned entrypc_srcline_idx = 0;
1856 : 11611 : dwarf_line_t entrypc_srcline;
1857 : : // open-code binary search for exact match
1858 : : {
1859 : 11611 : unsigned l = 0, h = nlines;
1860 [ + - ]: 127967 : while (l < h)
1861 : : {
1862 : 127967 : entrypc_srcline_idx = (l + h) / 2;
1863 : : const dwarf_line_t lr(dwarf_onesrcline(lines,
1864 [ + - ]: 127967 : entrypc_srcline_idx));
1865 [ + - ]: 127967 : Dwarf_Addr addr = lr.addr();
1866 [ + + ]: 127967 : if (addr == entrypc) { entrypc_srcline = lr; break; }
1867 [ + - ]: 116356 : else if (l + 1 == h) { break; } // ran off bottom of tree
1868 [ + + ]: 116356 : else if (addr < entrypc) { l = entrypc_srcline_idx; }
1869 : 127967 : else { h = entrypc_srcline_idx; }
1870 : : }
1871 : : }
1872 [ - + ]: 11611 : if (!entrypc_srcline)
1873 : : {
1874 [ # # ]: 0 : if (sess.verbose > 2)
1875 [ # # ][ # # ]: 0 : clog << _F("missing entrypc dwarf line record for function '%s'\n",
[ # # ]
1876 [ # # ]: 0 : it->name.c_str());
1877 : : // This is probably an inlined function. We'll end up using
1878 : : // its lowpc as a probe address.
1879 : 0 : continue;
1880 : : }
1881 : :
1882 [ + + ]: 11611 : if (entrypc == 0)
1883 : : {
1884 [ - + ]: 1 : if (sess.verbose > 2)
1885 [ # # ][ # # ]: 0 : clog << _F("null entrypc dwarf line record for function '%s'\n",
[ # # ]
1886 [ # # ]: 0 : it->name.c_str());
1887 : : // This is probably an inlined function. We'll skip this instance;
1888 : : // it is messed up.
1889 : 1 : continue;
1890 : : }
1891 : :
1892 [ - + ]: 11610 : if (sess.verbose>2)
1893 [ # # ][ # # ]: 0 : clog << _F("searching for prologue of function '%s' %#" PRIx64 "-%#" PRIx64
[ # # ]
1894 : : "@%s:%d\n", it->name.c_str(), entrypc, highpc, it->decl_file,
1895 [ # # ]: 0 : it->decl_line);
1896 : :
1897 : : // Now we go searching for the first line record that has a
1898 : : // file/line different from the one in the declaration.
1899 : : // Normally, this will be the next one. BUT:
1900 : : //
1901 : : // We may have to skip a few because some old compilers plop
1902 : : // in dummy line records for longer prologues. If we go too
1903 : : // far (addr >= highpc), we take the previous one. Or, it may
1904 : : // be the first one, if the function had no prologue, and thus
1905 : : // the entrypc maps to a statement in the body rather than the
1906 : : // declaration.
1907 : :
1908 : 11610 : unsigned postprologue_srcline_idx = entrypc_srcline_idx;
1909 : 11610 : bool ranoff_end = false;
1910 [ + - ]: 30108 : while (postprologue_srcline_idx < nlines)
1911 : : {
1912 [ + - ]: 18497 : dwarf_line_t lr(dwarf_onesrcline(lines, postprologue_srcline_idx));
1913 [ + - ]: 18497 : Dwarf_Addr postprologue_addr = lr.addr();
1914 [ + - ]: 18497 : const char* postprologue_file = lr.linesrc();
1915 [ + - ]: 18497 : int postprologue_lineno = lr.lineno();
1916 : :
1917 [ - + ]: 18497 : if (sess.verbose>2)
1918 [ # # ][ # # ]: 0 : clog << _F("checking line record %#" PRIx64 "@%s:%d\n", postprologue_addr,
1919 [ # # ]: 0 : postprologue_file, postprologue_lineno);
1920 : :
1921 [ + + ]: 18497 : if (postprologue_addr >= highpc)
1922 : : {
1923 : 1009 : ranoff_end = true;
1924 : 1009 : postprologue_srcline_idx --;
1925 : 1009 : continue;
1926 : : }
1927 [ + + + + : 46985 : if (ranoff_end ||
+ + ][ + + ]
1928 : 16479 : (strcmp (postprologue_file, it->decl_file) || // We have a winner!
1929 : 13018 : (postprologue_lineno != it->decl_line)))
1930 : : {
1931 : 11610 : it->prologue_end = postprologue_addr;
1932 : :
1933 [ - + ]: 11610 : if (sess.verbose>2)
1934 : : {
1935 [ # # ][ # # ]: 0 : clog << _F("prologue found function '%s'", it->name.c_str());
[ # # ][ # # ]
1936 : : // Add a little classification datum
1937 : : //TRANSLATORS: Here we're adding some classification datum (ie Prologue Free)
1938 [ # # ][ # # ]: 0 : if (postprologue_srcline_idx == entrypc_srcline_idx) clog << _(" (naked)");
1939 : : //TRANSLATORS: Here we're adding some classification datum (ie Prologue Free)
1940 [ # # ][ # # ]: 0 : if (ranoff_end) clog << _(" (tail-call?)");
1941 [ # # ][ # # ]: 0 : clog << " = 0x" << hex << postprologue_addr << dec << "\n";
[ # # ][ # # ]
[ # # ]
1942 : : }
1943 : :
1944 : : break;
1945 : : }
1946 : :
1947 : : // Let's try the next srcline.
1948 : 17488 : postprologue_srcline_idx ++;
1949 : : } // loop over srclines
1950 : :
1951 : : // if (strlen(it->decl_file) == 0) it->decl_file = NULL;
1952 : :
1953 : : } // loop over functions
1954 : :
1955 : : // XXX: how to free lines?
1956 : 59 : }
1957 : :
1958 : :
1959 : : bool
1960 : 357761 : dwflpp::function_entrypc (Dwarf_Addr * addr)
1961 : : {
1962 [ - + ]: 357761 : assert (function);
1963 : 357761 : return (dwarf_entrypc (function, addr) == 0);
1964 : : }
1965 : :
1966 : :
1967 : : bool
1968 : 213601 : dwflpp::die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr)
1969 : : {
1970 : 213601 : int rc = 0;
1971 [ + - ]: 213601 : string lookup_method;
1972 : :
1973 : 213601 : * addr = 0;
1974 : :
1975 [ + - ]: 213601 : lookup_method = "dwarf_entrypc";
1976 [ + - ]: 213601 : rc = dwarf_entrypc (die, addr);
1977 : :
1978 [ - + ]: 213601 : if (rc)
1979 : : {
1980 [ # # ]: 0 : lookup_method = "dwarf_ranges";
1981 : :
1982 : : Dwarf_Addr base;
1983 : : Dwarf_Addr begin;
1984 : : Dwarf_Addr end;
1985 [ # # ]: 0 : ptrdiff_t offset = dwarf_ranges (die, 0, &base, &begin, &end);
1986 [ # # ]: 0 : if (offset < 0) rc = -1;
1987 [ # # ]: 0 : else if (offset > 0)
1988 : : {
1989 : 0 : * addr = begin;
1990 : 0 : rc = 0;
1991 : :
1992 : : // Now we need to check that there are no more ranges
1993 : : // associated with this function, which could conceivably
1994 : : // happen if a function is inlined, then pieces of it are
1995 : : // split amongst different conditional branches. It's not
1996 : : // obvious which of them to favour. As a heuristic, we
1997 : : // pick the beginning of the first range, and ignore the
1998 : : // others (but with a warning).
1999 : :
2000 : 0 : unsigned extra = 0;
2001 [ # # ][ # # ]: 0 : while ((offset = dwarf_ranges (die, offset, &base, &begin, &end)) > 0)
2002 : 0 : extra ++;
2003 [ # # ]: 0 : if (extra)
2004 [ # # ][ # # ]: 0 : lookup_method += _F(", ignored %s more", lex_cast(extra).c_str());
[ # # ][ # # ]
[ # # ][ # # ]
2005 : : }
2006 : : }
2007 : :
2008 : : // PR10574: reject subprograms where the entrypc address turns out
2009 : : // to be 0, since they tend to correspond to duplicate-eliminated
2010 : : // COMDAT copies of C++ functions.
2011 [ + - ][ - + ]: 213601 : if (rc == 0 && *addr == 0)
2012 : : {
2013 [ # # ]: 0 : lookup_method += _(" (skip comdat)");
2014 : 0 : rc = 1;
2015 : : }
2016 : :
2017 [ - + ]: 213601 : if (sess.verbose > 2)
2018 [ # # ][ # # ]: 0 : clog << _F("entry-pc lookup (%s dieoffset: %s) = %#" PRIx64 " (rc %d)", lookup_method.c_str(),
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2019 [ # # ]: 0 : lex_cast_hex(dwarf_dieoffset(die)).c_str(), *addr, rc) << endl;
2020 : :
2021 [ + - ]: 213601 : return (rc == 0);
2022 : : }
2023 : :
2024 : :
2025 : : void
2026 : 357761 : dwflpp::function_die (Dwarf_Die *d)
2027 : : {
2028 [ - + ]: 357761 : assert (function);
2029 : 357761 : *d = *function;
2030 : 357761 : }
2031 : :
2032 : :
2033 : : void
2034 : 571357 : dwflpp::function_file (char const ** c)
2035 : : {
2036 [ - + ]: 571357 : assert (function);
2037 [ - + ]: 571357 : assert (c);
2038 : 571357 : *c = dwarf_decl_file (function);
2039 : 571357 : }
2040 : :
2041 : :
2042 : : void
2043 : 571603 : dwflpp::function_line (int *linep)
2044 : : {
2045 [ - + ]: 571603 : assert (function);
2046 : 571603 : dwarf_decl_line (function, linep);
2047 : 571603 : }
2048 : :
2049 : :
2050 : : bool
2051 : 829 : dwflpp::die_has_pc (Dwarf_Die & die, Dwarf_Addr pc)
2052 : : {
2053 : 829 : int res = dwarf_haspc (&die, pc);
2054 : : // dwarf_ranges will return -1 if a function die has no DW_AT_ranges
2055 : : // if (res == -1)
2056 : : // dwarf_assert ("dwarf_haspc", res);
2057 : 829 : return res == 1;
2058 : : }
2059 : :
2060 : :
2061 : : bool
2062 : 46 : dwflpp::inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr,
2063 : : Dwarf_Die& result)
2064 : : {
2065 : 46 : result = scope;
2066 : :
2067 : : // Sometimes we're in a bad scope to begin with -- just let it be. This can
2068 : : // happen for example if the compiler outputs a label PC that's just outside
2069 : : // the lexical scope. We can't really do anything about that, but variables
2070 : : // will probably not be accessible in this case.
2071 [ + - ][ - + ]: 46 : if (!die_has_pc(scope, addr))
2072 : 0 : return false;
2073 : :
2074 : : Dwarf_Die child, import;
2075 [ + - ]: 46 : int rc = dwarf_child(&result, &child);
2076 [ + + ]: 487 : while (rc == 0)
2077 : : {
2078 [ + - ]: 441 : switch (dwarf_tag (&child))
[ - + + ]
2079 : : {
2080 : : case DW_TAG_imported_unit:
2081 : : // The children of the imported unit need to be treated as if
2082 : : // they are inserted here. So look inside and set result if
2083 : : // found.
2084 [ # # ][ # # ]: 0 : if (dwarf_attr_die(&child, DW_AT_import, &import))
2085 : : {
2086 : : Dwarf_Die import_result;
2087 [ # # ][ # # ]: 0 : if (inner_die_containing_pc(import, addr, import_result))
2088 : : {
2089 : 0 : result = import_result;
2090 : 0 : return true;
2091 : : }
2092 : : }
2093 : 0 : break;
2094 : :
2095 : : // lexical tags to recurse within the same starting scope
2096 : : // NB: this intentionally doesn't cross into inlines!
2097 : : case DW_TAG_lexical_block:
2098 : : case DW_TAG_with_stmt:
2099 : : case DW_TAG_catch_block:
2100 : : case DW_TAG_try_block:
2101 : : case DW_TAG_entry_point:
2102 [ + - ][ + + ]: 19 : if (die_has_pc(child, addr))
2103 : : {
2104 : 5 : result = child;
2105 [ + - ]: 5 : rc = dwarf_child(&result, &child);
2106 : 5 : continue;
2107 : : }
2108 : : }
2109 [ + - ]: 436 : rc = dwarf_siblingof(&child, &child);
2110 : : }
2111 : 46 : return true;
2112 : : }
2113 : :
2114 : :
2115 : : void
2116 : 354 : dwflpp::loc2c_error (void *, const char *fmt, ...)
2117 : : {
2118 : 354 : const char *msg = "?";
2119 : 354 : char *tmp = NULL;
2120 : : int rc;
2121 : : va_list ap;
2122 : 354 : va_start (ap, fmt);
2123 : 354 : rc = vasprintf (& tmp, fmt, ap);
2124 [ - + ]: 354 : if (rc < 0)
2125 : 0 : msg = "?";
2126 : : else
2127 : 354 : msg = tmp;
2128 : 354 : va_end (ap);
2129 [ + - ][ + - ]: 354 : throw semantic_error (msg);
2130 : : }
2131 : :
2132 : :
2133 : : // This function generates code used for addressing computations of
2134 : : // target variables.
2135 : : void
2136 : 184 : dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address)
2137 : : {
2138 [ + - ]: 184 : int n = dwfl_module_relocations (module);
2139 [ + - ][ + - ]: 184 : dwfl_assert ("dwfl_module_relocations", n >= 0);
[ + - ]
2140 : 184 : Dwarf_Addr reloc_address = address;
2141 : 184 : const char *secname = "";
2142 [ + + ]: 184 : if (n > 1)
2143 : : {
2144 [ + - ]: 1 : int i = dwfl_module_relocate_address (module, &reloc_address);
2145 [ + - ][ + - ]: 1 : dwfl_assert ("dwfl_module_relocate_address", i >= 0);
[ + - ]
2146 [ + - ]: 1 : secname = dwfl_module_relocation_info (module, i, NULL);
2147 : : }
2148 : :
2149 [ - + ]: 184 : if (sess.verbose > 2)
2150 : : {
2151 [ # # ][ # # ]: 0 : clog << _F("emit dwarf addr %#" PRIx64 " => module %s section %s relocaddr %#" PRIx64,
[ # # ][ # # ]
[ # # ]
2152 : : address, module_name.c_str (), (secname ?: "null"),
2153 [ # # ]: 0 : reloc_address) << endl;
2154 : : }
2155 : :
2156 [ + + ][ + + ]: 184 : if (n > 0 && !(n == 1 && secname == NULL))
[ + - ]
2157 : : {
2158 [ + - ][ + - ]: 174 : dwfl_assert ("dwfl_module_relocation_info", secname);
[ + - ]
2159 [ + + ][ - + ]: 348 : if (n > 1 || secname[0] != '\0')
2160 : : {
2161 : : // This gives us the module name, and section name within the
2162 : : // module, for a kernel module (or other ET_REL module object).
2163 : 1 : obstack_printf (pool, "({ unsigned long addr = 0; ");
2164 : : obstack_printf (pool, "addr = _stp_kmodule_relocate (\"%s\",\"%s\",%#" PRIx64 "); ",
2165 [ + - ]: 1 : module_name.c_str(), secname, reloc_address);
2166 : 1 : obstack_printf (pool, "addr; })");
2167 : : }
2168 [ + - ][ + - ]: 173 : else if (n == 1 && module_name == TOK_KERNEL && secname[0] == '\0')
[ + - ][ + - ]
[ + - ]
2169 : : {
2170 : : // elfutils' way of telling us that this is a relocatable kernel address, which we
2171 : : // need to treat the same way here as dwarf_query::add_probe_point does: _stext.
2172 : 173 : address -= sess.sym_stext;
2173 : 173 : secname = "_stext";
2174 : : // Note we "cache" the result here through a static because the
2175 : : // kernel will never move after being loaded (unlike modules and
2176 : : // user-space dynamic share libraries).
2177 : 173 : obstack_printf (pool, "({ static unsigned long addr = 0; ");
2178 : : obstack_printf (pool, "if (addr==0) addr = _stp_kmodule_relocate (\"%s\",\"%s\",%#" PRIx64 "); ",
2179 [ + - ]: 173 : module_name.c_str(), secname, address); // PR10000 NB: not reloc_address
2180 : 173 : obstack_printf (pool, "addr; })");
2181 : : }
2182 : : else
2183 : : {
2184 [ # # ]: 0 : enable_task_finder (sess);
2185 : 0 : obstack_printf (pool, "({ unsigned long addr = 0; ");
2186 : : obstack_printf (pool, "addr = _stp_umodule_relocate (\"%s\",%#" PRIx64 ", current); ",
2187 [ # # ]: 0 : canonicalize_file_name(module_name.c_str()), address);
2188 : 0 : obstack_printf (pool, "addr; })");
2189 : : }
2190 : : }
2191 : : else
2192 : 10 : obstack_printf (pool, "%#" PRIx64 "UL", address); // assume as constant
2193 : 184 : }
2194 : :
2195 : :
2196 : : void
2197 : 184 : dwflpp::loc2c_emit_address (void *arg, struct obstack *pool,
2198 : : Dwarf_Addr address)
2199 : : {
2200 : 184 : static_cast<dwflpp *>(arg)->emit_address (pool, address);
2201 : 184 : }
2202 : :
2203 : :
2204 : : void
2205 : 3765 : dwflpp::print_locals(vector<Dwarf_Die>& scopes, ostream &o)
2206 : : {
2207 : : // XXX Shouldn't this be walking up to outer scopes too?
2208 : :
2209 : 3765 : print_locals_die(scopes[0], o);
2210 : 3765 : }
2211 : :
2212 : : void
2213 : 3765 : dwflpp::print_locals_die(Dwarf_Die& die, ostream &o)
2214 : : {
2215 : : // Try to get the first child of die.
2216 : : Dwarf_Die child, import;
2217 [ + - ][ + - ]: 3765 : if (dwarf_child (&die, &child) == 0)
2218 : : {
2219 [ + + ]: 38405 : do
2220 : : {
2221 : : const char *name;
2222 : : // Output each sibling's name (that is a variable or
2223 : : // parameter) to 'o'.
2224 [ + - ]: 38405 : switch (dwarf_tag (&child))
[ + - + ]
2225 : : {
2226 : : case DW_TAG_variable:
2227 : : case DW_TAG_formal_parameter:
2228 [ + - ]: 20607 : name = dwarf_diename (&child);
2229 [ + - ]: 20607 : if (name)
2230 [ + - ][ + - ]: 20607 : o << " $" << name;
2231 : 20607 : break;
2232 : : case DW_TAG_imported_unit:
2233 : : // Treat the imported unit children as if they are
2234 : : // children of the given DIE.
2235 [ # # ][ # # ]: 0 : if (dwarf_attr_die(&child, DW_AT_import, &import))
2236 [ # # ]: 0 : print_locals_die (import, o);
2237 : 0 : break;
2238 : : default:
2239 : 17798 : break;
2240 : : }
2241 : : }
2242 [ + - ]: 38405 : while (dwarf_siblingof (&child, &child) == 0);
2243 : : }
2244 : 3765 : }
2245 : :
2246 : :
2247 : : Dwarf_Attribute *
2248 : 186562 : dwflpp::find_variable_and_frame_base (vector<Dwarf_Die>& scopes,
2249 : : Dwarf_Addr pc,
2250 : : string const & local,
2251 : : const target_symbol *e,
2252 : : Dwarf_Die *vardie,
2253 : : Dwarf_Attribute *fb_attr_mem)
2254 : : {
2255 : 186562 : Dwarf_Die *scope_die = &scopes[0];
2256 : 186562 : Dwarf_Attribute *fb_attr = NULL;
2257 : :
2258 [ - + ]: 186562 : assert (cu);
2259 : :
2260 : 186562 : int declaring_scope = dwarf_getscopevar (&scopes[0], scopes.size(),
2261 : : local.c_str(),
2262 : : 0, NULL, 0, 0,
2263 [ + - ][ + - ]: 186562 : vardie);
2264 [ + + ]: 186562 : if (declaring_scope < 0)
2265 : : {
2266 [ + - ]: 3765 : stringstream alternatives;
2267 [ + - ]: 3765 : print_locals (scopes, alternatives);
2268 [ + - ][ + - ]: 3765 : if (e->cu_name == "")
2269 [ + - ][ + - ]: 18825 : throw semantic_error (_F("unable to find local '%s', [man error::dwarf] dieoffset %s in %s, near pc %s %s %s %s (%s)",
[ + - ][ + - ]
[ + - ]
2270 : : local.c_str(),
2271 : : lex_cast_hex(dwarf_dieoffset(scope_die)).c_str(),
2272 : : module_name.c_str(),
2273 : : lex_cast_hex(pc).c_str(),
2274 : : (scope_die == NULL) ? "" : _("in"),
2275 : : (dwarf_diename(scope_die) ?: "<unknown>"),
2276 : : (dwarf_diename(cu) ?: "<unknown>"),
2277 : : (alternatives.str() == ""
2278 : : ? (_("<no alternatives>"))
2279 : : : (_("alternatives:")
2280 : : + alternatives.str())).c_str()),
2281 [ + - ][ + - ]: 22590 : e->tok);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ - + ]
[ # # ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ - + ]
[ # # # # ]
2282 : : else
2283 [ # # ][ # # ]: 0 : throw semantic_error (_F("unable to find global '%s', [man error::dwarf] dieoffset %s in %s, %s %s %s (%s)",
[ # # ][ # # ]
2284 : : local.c_str(),
2285 : : lex_cast_hex(dwarf_dieoffset(scope_die)).c_str(),
2286 : : module_name.c_str(),
2287 : : (scope_die == NULL) ? "" : _("in"),
2288 : : (dwarf_diename(scope_die) ?: "<unknown>"),
2289 : : e->cu_name.c_str(),
2290 : : (alternatives.str() == ""
2291 : : ? (_("<no alternatives>"))
2292 : : : (_("alternatives:")
2293 : : + alternatives.str())).c_str()),
2294 [ # # ][ # # ]: 3765 : e->tok);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
2295 : : }
2296 : :
2297 : : /* Some GCC versions would output duplicate external variables, one
2298 : : without a location attribute. If so, try to find the other if it
2299 : : exists in the same scope. See GCC PR51410. */
2300 : : Dwarf_Attribute attr_mem;
2301 [ + - ][ + + ]: 367119 : if (dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem) == NULL
[ + + ][ + + ]
[ + - ][ + + ]
2302 [ + - ]: 181895 : && dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) == NULL
2303 [ + - ]: 2423 : && dwarf_attr_integrate (vardie, DW_AT_external, &attr_mem) != NULL
2304 [ + - ]: 4 : && dwarf_tag(&scopes[declaring_scope]) == DW_TAG_compile_unit)
2305 : : {
2306 : 4 : Dwarf_Die orig_vardie = *vardie;
2307 : 4 : bool alt_found = false;
2308 [ + - ][ + - ]: 4 : if (dwarf_child(&scopes[declaring_scope], vardie) == 0)
2309 [ + - ][ + + ]: 10400 : do
[ + + ]
2310 : : {
2311 : : // Note, not handling DW_TAG_imported_unit, assuming GCC
2312 : : // version is recent enough to not need this workaround if
2313 : : // we would see an imported unit.
2314 [ + - ][ + + ]: 5545 : if (dwarf_tag (vardie) == DW_TAG_variable
[ + + ][ + - ]
[ + - ][ - + ]
[ - + ]
2315 [ + - ][ + - ]: 333 : && strcmp (dwarf_diename (vardie), local.c_str ()) == 0
2316 [ + - ]: 4 : && (dwarf_attr_integrate (vardie, DW_AT_external, &attr_mem)
2317 : : != NULL)
2318 [ + - ]: 4 : && ((dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem)
2319 : : != NULL)
2320 [ + - ]: 4 : || (dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem)
2321 : : != NULL)))
2322 : 0 : alt_found = true;
2323 : : }
2324 [ + - ]: 5200 : while (!alt_found && dwarf_siblingof(vardie, vardie) == 0);
2325 : :
2326 [ + - ]: 4 : if (! alt_found)
2327 : 4 : *vardie = orig_vardie;
2328 : : }
2329 : :
2330 : : // Global vars don't need (cannot use) frame base in location descriptor.
2331 [ + - ][ + + ]: 182797 : if (e->cu_name != "")
2332 : 3 : return NULL;
2333 : :
2334 : : /* We start out walking the "lexical scopes" as returned by
2335 : : * as returned by dwarf_getscopes for the address, starting with the
2336 : : * declaring_scope that the variable was found in.
2337 : : */
2338 [ + - ]: 182794 : vector<Dwarf_Die> physcopes, *fbscopes = &scopes;
2339 [ + + ][ + + ]: 732572 : for (size_t inner = declaring_scope;
[ + + ]
2340 : 366286 : inner < fbscopes->size() && fb_attr == NULL;
2341 : : ++inner)
2342 : : {
2343 : 183492 : Dwarf_Die& scope = (*fbscopes)[inner];
2344 [ + - ]: 183492 : switch (dwarf_tag (&scope))
[ + + + ]
2345 : : {
2346 : : default:
2347 : 49 : continue;
2348 : : case DW_TAG_subprogram:
2349 : : case DW_TAG_entry_point:
2350 : : fb_attr = dwarf_attr_integrate (&scope,
2351 : : DW_AT_frame_base,
2352 [ + - ]: 182765 : fb_attr_mem);
2353 : 182765 : break;
2354 : : case DW_TAG_inlined_subroutine:
2355 : : /* Unless we already are going through the "pyshical die tree",
2356 : : * we now need to start walking the die tree where this
2357 : : * subroutine is inlined to find the appropriate frame base. */
2358 [ + - ]: 678 : if (declaring_scope != -1)
2359 : : {
2360 [ + - ][ + - ]: 678 : physcopes = getscopes_die(&scope);
[ + - ]
2361 [ + - ][ - + ]: 678 : if (physcopes.empty())
2362 : 0 : throw semantic_error (_F("unable to get die scopes for '%s' in an inlined subroutine",
2363 [ # # ][ # # ]: 0 : local.c_str()), e->tok);
[ # # ]
2364 : 678 : fbscopes = &physcopes;
2365 : 678 : inner = 0; // zero is current scope, for look will increase.
2366 : 678 : declaring_scope = -1;
2367 : : }
2368 : 678 : break;
2369 : : }
2370 : : }
2371 : :
2372 [ + - ]: 186562 : return fb_attr;
2373 : : }
2374 : :
2375 : :
2376 : : struct location *
2377 : 251339 : dwflpp::translate_location(struct obstack *pool,
2378 : : Dwarf_Attribute *attr, Dwarf_Die *die,
2379 : : Dwarf_Addr pc,
2380 : : Dwarf_Attribute *fb_attr,
2381 : : struct location **tail,
2382 : : const target_symbol *e)
2383 : : {
2384 : :
2385 : : /* DW_AT_data_member_location, can be either constant offsets
2386 : : (struct member fields), or full blown location expressions. */
2387 : :
2388 : : /* There is no location expression, but a constant value instead. */
2389 [ + - ][ + + ]: 251339 : if (dwarf_whatattr (attr) == DW_AT_const_value)
2390 : : {
2391 : : *tail = c_translate_constant (pool, &loc2c_error, this,
2392 [ + - ]: 902 : &loc2c_emit_address, 0, pc, attr);
2393 : 902 : return *tail;
2394 : : }
2395 : :
2396 : : Dwarf_Op *expr;
2397 : : size_t len;
2398 : :
2399 : : /* PR9768: formerly, we added pc+module_bias here. However, that bias value
2400 : : is not present in the pc value by the time we get it, so adding it would
2401 : : result in false negatives of variable reachibility. In other instances
2402 : : further below, the c_translate_FOO functions, the module_bias value used
2403 : : to be passed in, but instead should now be zero for the same reason. */
2404 : :
2405 : : retry:
2406 [ + - ]: 250437 : switch (dwarf_getlocation_addr (attr, pc /*+ module_bias*/, &expr, &len, 1))
[ + + + ]
2407 : : {
2408 : : case 1: /* Should always happen. */
2409 [ + - ]: 224578 : if (len > 0)
2410 : 224578 : break;
2411 : : /* Fall through. */
2412 : :
2413 : : case 0: /* Shouldn't happen.... but can, e.g. due to PR15123. */
2414 : : {
2415 [ + - ]: 25619 : Dwarf_Addr pc2 = pr15123_retry_addr (pc, die);
2416 [ - + ]: 25619 : if (pc2 != 0) {
2417 : 0 : pc = pc2;
2418 : 0 : goto retry;
2419 : : }
2420 : : }
2421 : :
2422 : : /* FALLTHROUGH */
2423 [ + - ]: 25619 : throw semantic_error (_F("not accessible at this address [man error::dwarf] (%s, dieoffset: %s)",
2424 : : lex_cast_hex(pc).c_str(), lex_cast_hex(dwarf_dieoffset(die)).c_str()),
2425 [ + - ][ + - ]: 51238 : e->tok);
[ + - ][ + - ]
[ + - ][ + - ]
2426 : :
2427 : : default: /* Shouldn't happen. */
2428 : : case -1:
2429 [ + - ][ + - ]: 25859 : throw semantic_error (_F("dwarf_getlocation_addr failed [man error::dwarf] , %s", dwarf_errmsg(-1)), e->tok);
[ + - ]
2430 : : }
2431 : :
2432 : : Dwarf_Op *cfa_ops;
2433 : : // pc is in the dw address space of the current module, which is what
2434 : : // c_translate_location expects. get_cfa_ops wants the global dwfl address.
2435 : : // cfa_ops only make sense for locals.
2436 [ + - ][ + + ]: 224578 : if (e->cu_name == "")
2437 : : {
2438 : 224574 : Dwarf_Addr addr = pc + module_bias;
2439 [ + - ]: 224574 : cfa_ops = get_cfa_ops (addr);
2440 : : }
2441 : : else
2442 : 4 : cfa_ops = NULL;
2443 : :
2444 : : return c_translate_location (pool, &loc2c_error, this,
2445 : : &loc2c_emit_address,
2446 : : 1, 0 /* PR9768 */,
2447 [ + - ]: 225480 : pc, attr, expr, len, tail, fb_attr, cfa_ops);
2448 : : }
2449 : :
2450 : :
2451 : : void
2452 : 2025 : dwflpp::print_members(Dwarf_Die *vardie, ostream &o, set<string> &dupes)
2453 : : {
2454 [ + - ]: 2025 : const int typetag = dwarf_tag (vardie);
2455 : :
2456 : : /* compile and partial unit included for recursion through
2457 : : imported_unit below. */
2458 [ + + ][ + - ]: 2025 : if (typetag != DW_TAG_structure_type &&
[ - + ][ # # ]
[ # # ]
2459 : : typetag != DW_TAG_class_type &&
2460 : : typetag != DW_TAG_union_type &&
2461 : : typetag != DW_TAG_compile_unit &&
2462 : : typetag != DW_TAG_partial_unit)
2463 : : {
2464 [ # # ][ # # ]: 0 : o << _F(" Error: %s isn't a struct/class/union", dwarf_type_name(vardie).c_str());
[ # # ][ # # ]
[ # # ][ # # ]
2465 : : return;
2466 : : }
2467 : :
2468 : : // Try to get the first child of vardie.
2469 : : Dwarf_Die die_mem, import;
2470 : 2025 : Dwarf_Die *die = &die_mem;
2471 [ + - ]: 2025 : switch (dwarf_child (vardie, die))
[ - - + ]
2472 : : {
2473 : : case 1: // No children.
2474 [ # # ][ # # ]: 0 : o << _F("%s is empty", dwarf_type_name(vardie).c_str());
[ # # ][ # # ]
[ # # ][ # # ]
2475 : 0 : break;
2476 : :
2477 : : case -1: // Error.
2478 : : default: // Shouldn't happen.
2479 [ # # ][ # # ]: 0 : o << dwarf_type_name(vardie)
[ # # ]
2480 [ # # ][ # # ]: 0 : << ": " << dwarf_errmsg (-1);
[ # # ]
2481 : 0 : break;
2482 : :
2483 : : case 0: // Success.
2484 : 2025 : break;
2485 : : }
2486 : :
2487 : : // Output each sibling's name to 'o'.
2488 [ + + ]: 72683 : do
2489 : : {
2490 [ + - ]: 72683 : int tag = dwarf_tag(die);
2491 : :
2492 : : /* The children of an imported_unit should be treated as members too. */
2493 [ - + ][ # # ]: 72683 : if (tag == DW_TAG_imported_unit
[ - + ]
2494 [ # # ]: 0 : && dwarf_attr_die(die, DW_AT_import, &import))
2495 [ # # ]: 0 : print_members(&import, o, dupes);
2496 : :
2497 [ - + ][ # # ]: 72683 : if (tag != DW_TAG_member && tag != DW_TAG_inheritance)
2498 : 0 : continue;
2499 : :
2500 [ + - ]: 72683 : const char *member = dwarf_diename (die) ;
2501 : :
2502 [ + - ][ + + ]: 72683 : if ( tag == DW_TAG_member && member != NULL )
2503 : : {
2504 : : // Only output if this is new, to avoid inheritance dupes.
2505 [ + - ][ + - ]: 144478 : if (dupes.insert(member).second)
[ + - ][ + - ]
2506 [ + - ][ + - ]: 72239 : o << " " << member;
2507 : : }
2508 : : else
2509 : : {
2510 : : Dwarf_Die temp_die;
2511 [ + - ][ - + ]: 444 : if (!dwarf_attr_die (die, DW_AT_type, &temp_die))
2512 : : {
2513 [ # # ][ # # ]: 0 : string source = dwarf_decl_file(die) ?: "<unknown source>";
[ # # ]
2514 : 0 : int line = -1;
2515 [ # # ]: 0 : dwarf_decl_line(die, &line);
2516 [ # # ][ # # ]: 0 : clog << _F("\n Error in obtaining type attribute for anonymous "
[ # # ]
2517 [ # # ]: 0 : "member at %s:%d", source.c_str(), line);
2518 [ # # ]: 0 : return;
2519 : : }
2520 : :
2521 [ + - ]: 444 : print_members(&temp_die, o, dupes);
2522 : : }
2523 : :
2524 : : }
2525 [ + - ]: 72683 : while (dwarf_siblingof (die, die) == 0);
2526 : : }
2527 : :
2528 : :
2529 : : bool
2530 : 87689 : dwflpp::find_struct_member(const target_symbol::component& c,
2531 : : Dwarf_Die *parentdie,
2532 : : Dwarf_Die *memberdie,
2533 : : vector<Dwarf_Die>& dies,
2534 : : vector<Dwarf_Attribute>& locs)
2535 : : {
2536 : : Dwarf_Attribute attr;
2537 : : Dwarf_Die die;
2538 : :
2539 : : /* With inheritance, a subclass may mask member names of parent classes, so
2540 : : * our search among the inheritance tree must be breadth-first rather than
2541 : : * depth-first (recursive). The parentdie is still our starting point. */
2542 [ + - ]: 87689 : deque<Dwarf_Die> inheritees(1, *parentdie);
2543 [ + - ][ + - ]: 96309 : for (; !inheritees.empty(); inheritees.pop_front())
[ + + ]
2544 : : {
2545 [ + - ][ + - ]: 87689 : switch (dwarf_child (&inheritees.front(), &die))
[ + - - ]
2546 : : {
2547 : : case 0: /* First child found. */
2548 : 87689 : break;
2549 : : case 1: /* No children. */
2550 : 0 : continue;
2551 : : case -1: /* Error. */
2552 : : default: /* Shouldn't happen */
2553 [ # # ]: 0 : throw semantic_error (dwarf_type_name(&inheritees.front()) + ": "
2554 : : + string (dwarf_errmsg (-1)),
2555 [ # # ][ # # ]: 0 : c.tok);
[ # # ][ # # ]
[ # # ][ # # ]
2556 : : }
2557 : :
2558 [ + + ]: 567619 : do
2559 : : {
2560 [ + - ]: 646688 : int tag = dwarf_tag(&die);
2561 : : /* recurse into imported units as if they are anonymoust structs */
2562 : : Dwarf_Die import;
2563 [ - + ][ # # ]: 646688 : if (tag == DW_TAG_imported_unit
[ # # ][ + - ]
2564 [ # # ]: 0 : && dwarf_attr_die(&die, DW_AT_import, &import)
2565 [ # # ]: 0 : && find_struct_member(c, &import, memberdie, dies, locs))
2566 : : goto success;
2567 : :
2568 [ + + ][ + - ]: 646688 : if (tag != DW_TAG_member && tag != DW_TAG_inheritance)
2569 : 51 : continue;
2570 : :
2571 [ + - ]: 646637 : const char *name = dwarf_diename(&die);
2572 [ - + ]: 646637 : if (tag == DW_TAG_inheritance)
2573 : : {
2574 : : /* Remember inheritee for breadth-first search. */
2575 : : Dwarf_Die inheritee;
2576 [ # # ][ # # ]: 0 : if (dwarf_attr_die (&die, DW_AT_type, &inheritee))
2577 [ # # ]: 0 : inheritees.push_back(inheritee);
2578 : : }
2579 [ + + ]: 646637 : else if (name == NULL)
2580 : : {
2581 : : /* Need to recurse for anonymous structs/unions. */
2582 : : Dwarf_Die subdie;
2583 [ + - ][ + - ]: 25242 : if (dwarf_attr_die (&die, DW_AT_type, &subdie) &&
[ + + ][ + + ]
2584 [ + - ]: 12621 : find_struct_member(c, &subdie, memberdie, dies, locs))
2585 : : goto success;
2586 : : }
2587 [ + - ][ + + ]: 634016 : else if (name == c.member)
2588 : : {
2589 : 646637 : *memberdie = die;
2590 : : goto success;
2591 : : }
2592 : : }
2593 [ + - ]: 567619 : while (dwarf_siblingof (&die, &die) == 0);
2594 : : }
2595 : :
2596 : 8620 : return false;
2597 : :
2598 : : success:
2599 : : /* As we unwind the recursion, we need to build the chain of
2600 : : * locations that got to the final answer. */
2601 [ + - ][ + + ]: 79069 : if (dwarf_attr_integrate (&die, DW_AT_data_member_location, &attr))
2602 : : {
2603 [ + - ][ + - ]: 72602 : dies.insert(dies.begin(), die);
2604 [ + - ][ + - ]: 72602 : locs.insert(locs.begin(), attr);
2605 : : }
2606 : :
2607 : : /* Union members don't usually have a location,
2608 : : * but just use the containing union's location. */
2609 [ + - ][ - + ]: 6467 : else if (dwarf_tag(parentdie) != DW_TAG_union_type)
2610 : 0 : throw semantic_error (_F("no location for field '%s':%s",
2611 [ # # ][ # # ]: 0 : c.member.c_str(), dwarf_errmsg(-1)), c.tok);
[ # # ][ # # ]
2612 : :
2613 [ + - ]: 87689 : return true;
2614 : : }
2615 : :
2616 : :
2617 : : static inline void
2618 : 109775 : dwarf_die_type (Dwarf_Die *die, Dwarf_Die *typedie_mem, const token *tok=NULL)
2619 : : {
2620 [ - + ]: 109775 : if (!dwarf_attr_die (die, DW_AT_type, typedie_mem))
2621 [ # # ][ # # ]: 0 : throw semantic_error (_F("cannot get type of field: %s", dwarf_errmsg(-1)), tok);
[ # # ]
2622 : 109775 : }
2623 : :
2624 : :
2625 : : void
2626 : 188860 : dwflpp::translate_components(struct obstack *pool,
2627 : : struct location **tail,
2628 : : Dwarf_Addr pc,
2629 : : const target_symbol *e,
2630 : : Dwarf_Die *vardie,
2631 : : Dwarf_Die *typedie,
2632 : : unsigned first)
2633 : : {
2634 : 188860 : unsigned i = first;
2635 [ + + ]: 298635 : while (i < e->components.size())
2636 : : {
2637 : 111356 : const target_symbol::component& c = e->components[i];
2638 : :
2639 : : /* XXX: This would be desirable, but we don't get the target_symbol token,
2640 : : and printing that gives us the file:line number too early anyway. */
2641 : : #if 0
2642 : : // Emit a marker to note which field is being access-attempted, to give
2643 : : // better error messages if deref() fails.
2644 : : string piece = string(...target_symbol token...) + string ("#") + lex_cast(components[i].second);
2645 : : obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str());
2646 : : #endif
2647 : :
2648 [ + - ][ + - : 111356 : switch (dwarf_tag (typedie))
+ + + - -
- ]
2649 : : {
2650 : : case DW_TAG_typedef:
2651 : : case DW_TAG_const_type:
2652 : : case DW_TAG_volatile_type:
2653 : : /* Just iterate on the referent type. */
2654 [ + - ]: 9000 : dwarf_die_type (typedie, typedie, c.tok);
2655 : 9000 : break;
2656 : :
2657 : : case DW_TAG_reference_type:
2658 : : case DW_TAG_rvalue_reference_type:
2659 [ # # ]: 0 : if (pool)
2660 [ # # ]: 0 : c_translate_pointer (pool, 1, 0 /* PR9768*/, typedie, tail);
2661 [ # # ]: 0 : dwarf_die_type (typedie, typedie, c.tok);
2662 : 0 : break;
2663 : :
2664 : : case DW_TAG_pointer_type:
2665 : : /* A pointer with no type is a void* -- can't dereference it. */
2666 [ + - ][ - + ]: 26688 : if (!dwarf_hasattr_integrate (typedie, DW_AT_type))
2667 : 0 : throw semantic_error (_F("invalid access '%s' vs '%s'", lex_cast(c).c_str(),
2668 [ # # ][ # # ]: 0 : dwarf_type_name(typedie).c_str()), c.tok);
[ # # ][ # # ]
[ # # ][ # # ]
2669 : :
2670 [ + + ]: 26688 : if (pool)
2671 [ + - ]: 26664 : c_translate_pointer (pool, 1, 0 /* PR9768*/, typedie, tail);
2672 [ + + ][ + + ]: 26688 : if (c.type != target_symbol::comp_literal_array_index &&
2673 : : c.type != target_symbol::comp_expression_array_index)
2674 : : {
2675 [ + - ]: 26654 : dwarf_die_type (typedie, typedie, c.tok);
2676 : 26654 : break;
2677 : : }
2678 : : /* else fall through as an array access */
2679 : :
2680 : : case DW_TAG_array_type:
2681 [ + + ]: 634 : if (c.type == target_symbol::comp_literal_array_index)
2682 : : {
2683 [ + + ]: 596 : if (pool)
2684 : : c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail,
2685 [ + - ]: 582 : NULL, c.num_index);
2686 : : }
2687 [ + - ]: 38 : else if (c.type == target_symbol::comp_expression_array_index)
2688 : : {
2689 [ + - ][ + - ]: 38 : string index = "STAP_ARG_index" + lex_cast(i);
[ + - ]
2690 [ + + ]: 38 : if (pool)
2691 : : c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail,
2692 [ + - ][ + - ]: 38 : index.c_str(), 0);
[ + - ]
2693 : : }
2694 : : else
2695 : 0 : throw semantic_error (_F("invalid access '%s' for array type",
2696 [ # # ][ # # ]: 0 : lex_cast(c).c_str()), c.tok);
[ # # ][ # # ]
2697 : :
2698 [ + - ]: 634 : dwarf_die_type (typedie, typedie, c.tok);
2699 : 634 : *vardie = *typedie;
2700 : 634 : ++i;
2701 : 634 : break;
2702 : :
2703 : : case DW_TAG_structure_type:
2704 : : case DW_TAG_union_type:
2705 : : case DW_TAG_class_type:
2706 [ - + ]: 75068 : if (c.type != target_symbol::comp_struct_member)
2707 : 0 : throw semantic_error (_F("invalid access '%s' for %s",
2708 [ # # ][ # # ]: 0 : lex_cast(c).c_str(), dwarf_type_name(typedie).c_str()));
[ # # ][ # # ]
[ # # ][ # # ]
2709 : :
2710 [ + - ][ + + ]: 75068 : if (dwarf_hasattr(typedie, DW_AT_declaration))
2711 : : {
2712 [ + - ]: 367 : Dwarf_Die *tmpdie = declaration_resolve(typedie);
2713 [ - + ]: 367 : if (tmpdie == NULL)
2714 [ # # ][ # # ]: 0 : throw semantic_error (_F("unresolved %s", dwarf_type_name(typedie).c_str()), c.tok);
[ # # ][ # # ]
2715 : 367 : *typedie = *tmpdie;
2716 : : }
2717 : :
2718 : : {
2719 [ + - ]: 75068 : vector<Dwarf_Die> dies;
2720 [ + - ]: 75068 : vector<Dwarf_Attribute> locs;
2721 [ + - ][ + + ]: 75068 : if (!find_struct_member(c, typedie, vardie, dies, locs))
2722 : : {
2723 : : /* Add a file:line hint for anonymous types */
2724 [ + - ]: 1581 : string source;
2725 [ + - ][ - + ]: 1581 : if (!dwarf_hasattr_integrate(typedie, DW_AT_name))
2726 : : {
2727 : : int line;
2728 [ # # ]: 0 : const char *file = dwarf_decl_file(typedie);
2729 [ # # ][ # # ]: 0 : if (file && dwarf_decl_line(typedie, &line) == 0)
[ # # ][ # # ]
2730 : : source = " (" + string(file) + ":"
2731 [ # # ][ # # ]: 0 : + lex_cast(line) + ")";
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2732 : : }
2733 : :
2734 [ + - ]: 1581 : string alternatives;
2735 [ + - ]: 1581 : stringstream members;
2736 [ + - ]: 1581 : set<string> member_dupes;
2737 [ + - ]: 1581 : print_members(typedie, members, member_dupes);
2738 [ + - ][ + - ]: 1581 : if (members.str().size() != 0)
[ + - ][ + - ]
2739 [ + - ][ + - ]: 1581 : alternatives = " (alternatives:" + members.str() + ")";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2740 : 1581 : throw semantic_error(_F("unable to find member '%s' for %s%s%s", c.member.c_str(),
2741 : : dwarf_type_name(typedie).c_str(), source.c_str(),
2742 [ + - ][ + - ]: 1581 : alternatives.c_str()), c.tok);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2743 : : }
2744 : :
2745 [ + + ]: 146089 : for (unsigned j = 0; j < locs.size(); ++j)
2746 [ + + ]: 72602 : if (pool)
2747 : 72546 : translate_location (pool, &locs[j], &dies[j],
2748 [ + - ][ + - ]: 147614 : pc, NULL, tail, e);
[ + - ]
2749 : : }
2750 : :
2751 [ + - ]: 73487 : dwarf_die_type (vardie, typedie, c.tok);
2752 : 73487 : ++i;
2753 : 73487 : break;
2754 : :
2755 : : case DW_TAG_enumeration_type:
2756 : : case DW_TAG_base_type:
2757 : 0 : throw semantic_error (_F("invalid access '%s' vs. %s", lex_cast(c).c_str(),
2758 [ # # ][ # # ]: 0 : dwarf_type_name(typedie).c_str()), c.tok);
[ # # ][ # # ]
[ # # ][ # # ]
2759 : : break;
2760 : :
2761 : : case -1:
2762 [ # # ][ # # ]: 0 : throw semantic_error (_F("cannot find type: %s", dwarf_errmsg(-1)), c.tok);
[ # # ]
2763 : : break;
2764 : :
2765 : : default:
2766 [ # # ]: 0 : throw semantic_error (_F("%s: unexpected type tag %s", dwarf_type_name(typedie).c_str(),
2767 [ # # ][ # # ]: 1581 : lex_cast(dwarf_tag(typedie)).c_str()), c.tok);
[ # # ][ # # ]
[ # # ][ # # ]
2768 : : break;
2769 : : }
2770 : : }
2771 : 187279 : }
2772 : :
2773 : :
2774 : : void
2775 : 339528 : dwflpp::resolve_unqualified_inner_typedie (Dwarf_Die *typedie,
2776 : : Dwarf_Die *innerdie,
2777 : : const target_symbol *e)
2778 : : {
2779 : 339528 : int typetag = dwarf_tag (typedie);
2780 : 339528 : *innerdie = *typedie;
2781 [ + + ][ + + ]: 420620 : while (typetag == DW_TAG_typedef ||
[ + + ][ + + ]
2782 : : typetag == DW_TAG_const_type ||
2783 : : typetag == DW_TAG_volatile_type)
2784 : : {
2785 [ + + ]: 81117 : if (!dwarf_attr_die (innerdie, DW_AT_type, innerdie))
2786 [ + - ][ + - ]: 25 : throw semantic_error (_F("cannot get type of pointee: %s", dwarf_errmsg(-1)), e->tok);
[ + - ]
2787 : 81092 : typetag = dwarf_tag (innerdie);
2788 : : }
2789 : 339503 : }
2790 : :
2791 : :
2792 : : void
2793 : 184810 : dwflpp::translate_final_fetch_or_store (struct obstack *pool,
2794 : : struct location **tail,
2795 : : Dwarf_Addr /*module_bias*/,
2796 : : Dwarf_Die *vardie,
2797 : : Dwarf_Die *start_typedie,
2798 : : bool lvalue,
2799 : : const target_symbol *e,
2800 : : string &,
2801 : : string &,
2802 : : exp_type & ty)
2803 : : {
2804 : : /* First boil away any qualifiers associated with the type DIE of
2805 : : the final location to be accessed. */
2806 : :
2807 : 184810 : Dwarf_Die typedie_mem, *typedie = &typedie_mem;
2808 [ + - ]: 184810 : resolve_unqualified_inner_typedie (start_typedie, typedie, e);
2809 : :
2810 : : /* If we're looking for an address, then we can just provide what
2811 : : we computed to this point, without using a fetch/store. */
2812 [ + + ]: 184810 : if (e->addressof)
2813 : : {
2814 [ - + ]: 686 : if (lvalue)
2815 [ # # ][ # # ]: 0 : throw semantic_error (_("cannot write to member address"), e->tok);
2816 : :
2817 [ + - ][ + + ]: 686 : if (dwarf_hasattr_integrate (vardie, DW_AT_bit_offset))
2818 [ + - ][ + - ]: 1 : throw semantic_error (_("cannot take address of bit-field"), e->tok);
2819 : :
2820 [ + + ]: 685 : c_translate_addressof (pool, 1, 0, vardie, typedie, tail, "STAP_RETVALUE");
2821 : 683 : ty = pe_long;
2822 : 183124 : return;
2823 : : }
2824 : :
2825 : : /* Then switch behavior depending on the type of fetch/store we
2826 : : want, and the type and pointer-ness of the final location. */
2827 : :
2828 [ + - ]: 184124 : int typetag = dwarf_tag (typedie);
2829 [ - + + + : 184124 : switch (typetag)
+ ]
2830 : : {
2831 : : default:
2832 : 0 : throw semantic_error (_F("unsupported type tag %s for %s", lex_cast(typetag).c_str(),
2833 [ # # ][ # # ]: 0 : dwarf_type_name(typedie).c_str()), e->tok);
[ # # ][ # # ]
[ # # ][ # # ]
2834 : : break;
2835 : :
2836 : : case DW_TAG_structure_type:
2837 : : case DW_TAG_class_type:
2838 : : case DW_TAG_union_type:
2839 : 1331 : throw semantic_error (_F("'%s' is being accessed instead of a member",
2840 [ + - ][ + - ]: 1331 : dwarf_type_name(typedie).c_str()), e->tok);
[ + - ][ + - ]
2841 : : break;
2842 : :
2843 : : case DW_TAG_base_type:
2844 : :
2845 : : // Reject types we can't handle in systemtap
2846 : : {
2847 : : Dwarf_Attribute encoding_attr;
2848 : 98859 : Dwarf_Word encoding = (Dwarf_Word) -1;
2849 : : dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, &encoding_attr),
2850 [ + - ][ + - ]: 98859 : & encoding);
2851 [ - + ]: 98859 : if (encoding == (Dwarf_Word) -1)
2852 : : {
2853 : : // clog << "bad type1 " << encoding << " diestr" << endl;
2854 : 0 : throw semantic_error (_F("unsupported type (mystery encoding %s for %s", lex_cast(encoding).c_str(),
2855 [ # # ][ # # ]: 0 : dwarf_type_name(typedie).c_str()), e->tok);
[ # # ][ # # ]
[ # # ][ # # ]
2856 : : }
2857 : :
2858 [ + - ][ - + ]: 98859 : if (encoding == DW_ATE_float
2859 : : || encoding == DW_ATE_complex_float
2860 : : /* XXX || many others? */)
2861 : : {
2862 : : // clog << "bad type " << encoding << " diestr" << endl;
2863 : 0 : throw semantic_error (_F("unsupported type (encoding %s) for %s", lex_cast(encoding).c_str(),
2864 [ # # ][ # # ]: 98859 : dwarf_type_name(typedie).c_str()), e->tok);
[ # # ][ # # ]
[ # # ][ # # ]
2865 : : }
2866 : : }
2867 : : // Fallthrough. enumeration_types are always scalar.
2868 : : case DW_TAG_enumeration_type:
2869 : :
2870 : 99547 : ty = pe_long;
2871 [ + + ]: 99547 : if (lvalue)
2872 : : c_translate_store (pool, 1, 0 /* PR9768 */, vardie, typedie, tail,
2873 [ + - ]: 17 : "STAP_ARG_value");
2874 : : else
2875 : : c_translate_fetch (pool, 1, 0 /* PR9768 */, vardie, typedie, tail,
2876 [ + + ]: 99530 : "STAP_RETVALUE");
2877 : 99195 : break;
2878 : :
2879 : : case DW_TAG_array_type:
2880 : : case DW_TAG_pointer_type:
2881 : : case DW_TAG_reference_type:
2882 : : case DW_TAG_rvalue_reference_type:
2883 : :
2884 [ + + ]: 83246 : if (lvalue)
2885 : : {
2886 : 1 : ty = pe_long;
2887 [ - + ]: 1 : if (typetag == DW_TAG_array_type)
2888 [ # # ][ # # ]: 0 : throw semantic_error (_("cannot write to array address"), e->tok);
2889 [ + - ][ - + ]: 1 : if (typetag == DW_TAG_reference_type ||
2890 : : typetag == DW_TAG_rvalue_reference_type)
2891 [ # # ][ # # ]: 1686 : throw semantic_error (_("cannot write to reference"), e->tok);
2892 [ - + ]: 1 : assert (typetag == DW_TAG_pointer_type);
2893 : : c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail,
2894 [ + - ]: 1 : "STAP_ARG_value");
2895 : : }
2896 : : else
2897 : : {
2898 : : // We have the pointer: cast it to an integral type via &(*(...))
2899 : :
2900 : : // NB: per bug #1187, at one point char*-like types were
2901 : : // automagically converted here to systemtap string values.
2902 : : // For several reasons, this was taken back out, leaving
2903 : : // pointer-to-string "conversion" (copying) to tapset functions.
2904 : :
2905 : 83245 : ty = pe_long;
2906 [ + + ]: 83245 : if (typetag == DW_TAG_array_type)
2907 [ + - ]: 694 : c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail, NULL, 0);
2908 : : else
2909 [ + - ]: 82551 : c_translate_pointer (pool, 1, 0 /* PR9768 */, typedie, tail);
2910 : : c_translate_addressof (pool, 1, 0 /* PR9768 */, NULL, NULL, tail,
2911 [ + - ]: 83245 : "STAP_RETVALUE");
2912 : : }
2913 : 182441 : break;
2914 : : }
2915 : : }
2916 : :
2917 : :
2918 : : string
2919 : 183124 : dwflpp::express_as_string (string prelude,
2920 : : string postlude,
2921 : : struct location *head)
2922 : : {
2923 : 183124 : size_t bufsz = 0;
2924 : 183124 : char *buf = 0; // NB: it would leak to pre-allocate a buffer here
2925 : 183124 : FILE *memstream = open_memstream (&buf, &bufsz);
2926 [ - + ]: 183124 : assert(memstream);
2927 : :
2928 [ + - ]: 183124 : fprintf(memstream, "{\n");
2929 [ + - ][ + - ]: 183124 : fprintf(memstream, "%s", prelude.c_str());
2930 : :
2931 : : unsigned int stack_depth;
2932 [ + - ]: 183124 : bool deref = c_emit_location (memstream, head, 1, &stack_depth);
2933 : :
2934 : : // Ensure that DWARF keeps loc2c to a "reasonable" stack size
2935 : : // 32 intptr_t leads to max 256 bytes on the stack
2936 [ - + ]: 183124 : if (stack_depth > 32)
2937 [ # # ][ # # ]: 0 : throw semantic_error("oversized DWARF stack");
2938 : :
2939 [ + - ][ + - ]: 183124 : fprintf(memstream, "%s", postlude.c_str());
2940 [ + - ]: 183124 : fprintf(memstream, " goto out;\n");
2941 : :
2942 : : // dummy use of deref_fault label, to disable warning if deref() not used
2943 [ + - ]: 183124 : fprintf(memstream, "if (0) goto deref_fault;\n");
2944 : :
2945 : : // XXX: deref flag not reliable; emit fault label unconditionally
2946 : : (void) deref;
2947 : : fprintf(memstream,
2948 : : "deref_fault:\n"
2949 [ + - ]: 183124 : " goto out;\n");
2950 [ + - ]: 183124 : fprintf(memstream, "}\n");
2951 : :
2952 [ + - ]: 183124 : fclose (memstream);
2953 [ + - ]: 183124 : string result(buf);
2954 : 183124 : free (buf);
2955 : 183124 : return result;
2956 : : }
2957 : :
2958 : : Dwarf_Addr
2959 : 4 : dwflpp::vardie_from_symtable (Dwarf_Die *vardie, Dwarf_Addr *addr)
2960 : : {
2961 [ - + ]: 4 : const char *name = dwarf_linkage_name (vardie) ?: dwarf_diename (vardie);
2962 : :
2963 [ - + ]: 4 : if (sess.verbose > 2)
2964 [ # # ]: 0 : clog << _F("finding symtable address for %s\n", name);
2965 : :
2966 : 4 : *addr = 0;
2967 : 4 : int syms = dwfl_module_getsymtab (module);
2968 [ + - ][ + - ]: 4 : dwfl_assert (_("Getting symbols"), syms >= 0);
[ + - ]
2969 : :
2970 [ + + ][ + - ]: 389985 : for (int i = 0; *addr == 0 && i < syms; i++)
[ + + ]
2971 : : {
2972 : : GElf_Sym sym;
2973 : : GElf_Word shndxp;
2974 [ + - ]: 389981 : const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp);
2975 [ + - ][ + + ]: 389981 : if (symname
[ + - ][ + + ]
[ + - ]
2976 : 389981 : && ! strcmp (name, symname)
2977 : : && sym.st_shndx != SHN_UNDEF
2978 : : && (GELF_ST_TYPE (sym.st_info) == STT_NOTYPE // PR13284
2979 : : || GELF_ST_TYPE (sym.st_info) == STT_OBJECT))
2980 : 4 : *addr = sym.st_value;
2981 : : }
2982 : :
2983 : : // Don't relocate for the kernel, or kernel modules we handle those
2984 : : // specially in emit_address.
2985 [ + - ][ - + ]: 4 : if (dwfl_module_relocations (module) == 1 && module_name != TOK_KERNEL)
[ - + ]
2986 : 0 : dwfl_module_relocate_address (module, addr);
2987 : :
2988 [ - + ]: 4 : if (sess.verbose > 2)
2989 [ # # ]: 0 : clog << _F("found %s @%#" PRIx64 "\n", name, *addr);
2990 : :
2991 : 4 : return *addr;
2992 : : }
2993 : :
2994 : : string
2995 : 184981 : dwflpp::literal_stmt_for_local (vector<Dwarf_Die>& scopes,
2996 : : Dwarf_Addr pc,
2997 : : string const & local,
2998 : : const target_symbol *e,
2999 : : bool lvalue,
3000 : : exp_type & ty)
3001 : : {
3002 : : Dwarf_Die vardie;
3003 : 184981 : Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
3004 : :
3005 : : fb_attr = find_variable_and_frame_base (scopes, pc, local, e,
3006 [ + + ]: 184981 : &vardie, &fb_attr_mem);
3007 : :
3008 [ - + ]: 181216 : if (sess.verbose>2)
3009 : : {
3010 [ # # ][ # # ]: 0 : if (e->cu_name == "")
3011 [ # # ][ # # ]: 0 : clog << _F("finding location for local '%s' near address %#" PRIx64
[ # # ]
3012 : : ", module bias %#" PRIx64 "\n", local.c_str(), pc,
3013 [ # # ]: 0 : module_bias);
3014 : : else
3015 [ # # ][ # # ]: 0 : clog << _F("finding location for global '%s' in CU '%s'\n",
[ # # ][ # # ]
3016 [ # # ]: 0 : local.c_str(), e->cu_name.c_str());
3017 : : }
3018 : :
3019 : :
3020 : : #define obstack_chunk_alloc malloc
3021 : : #define obstack_chunk_free free
3022 : :
3023 : : struct obstack pool;
3024 [ + - ]: 181216 : obstack_init (&pool);
3025 : 181216 : struct location *tail = NULL;
3026 : :
3027 : : /* Given $foo->bar->baz[NN], translate the location of foo. */
3028 : :
3029 : : struct location *head;
3030 : :
3031 : : Dwarf_Attribute attr_mem;
3032 [ + - ][ + + ]: 361530 : if (dwarf_attr_integrate (&vardie, DW_AT_const_value, &attr_mem) == NULL
[ + + ][ + + ]
3033 [ + - ]: 180314 : && dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL)
3034 : : {
3035 : : Dwarf_Op addr_loc;
3036 : 2423 : memset(&addr_loc, 0, sizeof(Dwarf_Op));
3037 : 2423 : addr_loc.atom = DW_OP_addr;
3038 : : // If it is an external variable try the symbol table. PR10622.
3039 [ + - ][ + + ]: 2427 : if (dwarf_attr_integrate (&vardie, DW_AT_external, &attr_mem) != NULL
[ + - ][ + + ]
3040 [ + - ]: 4 : && vardie_from_symtable (&vardie, &addr_loc.number) != 0)
3041 : : {
3042 : : head = c_translate_location (&pool, &loc2c_error, this,
3043 : : &loc2c_emit_address,
3044 : : 1, 0, pc,
3045 [ + - ]: 4 : NULL, &addr_loc, 1, &tail, NULL, NULL);
3046 : : }
3047 : : else
3048 [ + - ]: 2419 : throw semantic_error (_F("failed to retrieve location attribute for '%s' [man error::dwarf] (dieoffset: %s)",
3049 [ + - ][ + - ]: 4838 : local.c_str(), lex_cast_hex(dwarf_dieoffset(&vardie)).c_str()), e->tok);
[ + - ][ + - ]
[ + - ]
3050 : : }
3051 : : else
3052 [ + + ]: 178793 : head = translate_location (&pool, &attr_mem, &vardie, pc, fb_attr, &tail, e);
3053 : :
3054 : : /* Translate the ->bar->baz[NN] parts. */
3055 : :
3056 : : Dwarf_Die typedie;
3057 [ + - ][ - + ]: 152938 : if (dwarf_attr_die (&vardie, DW_AT_type, &typedie) == NULL)
3058 [ # # ][ # # ]: 0 : throw semantic_error(_F("failed to retrieve type attribute for '%s' [man error::dwarf] (dieoffset: %s)", local.c_str(), lex_cast_hex(dwarf_dieoffset(&vardie)).c_str()), e->tok);
[ # # ][ # # ]
[ # # ][ # # ]
3059 : :
3060 [ + + ]: 152938 : translate_components (&pool, &tail, pc, e, &vardie, &typedie);
3061 : :
3062 : : /* Translate the assignment part, either
3063 : : x = $foo->bar->baz[NN]
3064 : : or
3065 : : $foo->bar->baz[NN] = x
3066 : : */
3067 : :
3068 [ + - ][ + - ]: 152688 : string prelude, postlude;
3069 : : translate_final_fetch_or_store (&pool, &tail, module_bias,
3070 : : &vardie, &typedie, lvalue, e,
3071 [ + + ]: 152688 : prelude, postlude, ty);
3072 : :
3073 : : /* Write the translation to a string. */
3074 [ + - ][ + - ]: 151011 : string result = express_as_string(prelude, postlude, head);
[ + - ][ + - ]
[ + - ]
3075 [ - + ][ # # ]: 151011 : obstack_free (&pool, 0);
[ + - ]
3076 [ + - ][ + - ]: 184981 : return result;
3077 : : }
3078 : :
3079 : : Dwarf_Die*
3080 : 1581 : dwflpp::type_die_for_local (vector<Dwarf_Die>& scopes,
3081 : : Dwarf_Addr pc,
3082 : : string const & local,
3083 : : const target_symbol *e,
3084 : : Dwarf_Die *typedie)
3085 : : {
3086 : : Dwarf_Die vardie;
3087 : : Dwarf_Attribute attr_mem;
3088 : :
3089 [ + - ]: 1581 : find_variable_and_frame_base (scopes, pc, local, e, &vardie, &attr_mem);
3090 : :
3091 [ + - ][ - + ]: 1581 : if (dwarf_attr_die (&vardie, DW_AT_type, typedie) == NULL)
3092 [ # # ][ # # ]: 0 : throw semantic_error(_F("failed to retrieve type attribute for '%s' [man error::dwarf]", local.c_str()), e->tok);
[ # # ]
3093 : :
3094 [ + - ]: 1581 : translate_components (NULL, NULL, pc, e, &vardie, typedie);
3095 : 1581 : return typedie;
3096 : : }
3097 : :
3098 : :
3099 : : string
3100 : 16240 : dwflpp::literal_stmt_for_return (Dwarf_Die *scope_die,
3101 : : Dwarf_Addr pc,
3102 : : const target_symbol *e,
3103 : : bool lvalue,
3104 : : exp_type & ty)
3105 : : {
3106 [ - + ]: 16240 : if (sess.verbose>2)
3107 [ # # ][ # # ]: 0 : clog << _F("literal_stmt_for_return: finding return value for %s (%s)\n",
[ # # ][ # # ]
[ # # ][ # # ]
3108 [ # # ]: 0 : (dwarf_diename(scope_die) ?: "<unknown>"), (dwarf_diename(cu) ?: "<unknown>"));
3109 : :
3110 : : struct obstack pool;
3111 [ + - ]: 16240 : obstack_init (&pool);
3112 : 16240 : struct location *tail = NULL;
3113 : :
3114 : : /* Given $return->bar->baz[NN], translate the location of return. */
3115 : : const Dwarf_Op *locops;
3116 : : int nlocops = dwfl_module_return_value_location (module, scope_die,
3117 [ + - ]: 16240 : &locops);
3118 [ - + ]: 16240 : if (nlocops < 0)
3119 : : {
3120 [ # # ][ # # ]: 0 : throw semantic_error(_F("failed to retrieve return value location for %s [man error::dwarf] (%s)",
3121 : : (dwarf_diename(scope_die) ?: "<unknown>"),
3122 [ # # ][ # # ]: 0 : (dwarf_diename(cu) ?: "<unknown>")), e->tok);
[ # # ][ # # ]
3123 : : }
3124 : : // the function has no return value (e.g. "void" in C)
3125 [ + + ]: 16240 : else if (nlocops == 0)
3126 : : {
3127 [ + - ][ + - ]: 464 : throw semantic_error(_F("function %s (%s) has no return value",
3128 : : (dwarf_diename(scope_die) ?: "<unknown>"),
3129 [ + - ][ + - ]: 696 : (dwarf_diename(cu) ?: "<unknown>")), e->tok);
[ + - ][ + - ]
3130 : : }
3131 : :
3132 : : struct location *head = c_translate_location (&pool, &loc2c_error, this,
3133 : : &loc2c_emit_address,
3134 : : 1, 0 /* PR9768 */,
3135 : : pc, NULL, locops, nlocops,
3136 [ + - ]: 16008 : &tail, NULL, NULL);
3137 : :
3138 : : /* Translate the ->bar->baz[NN] parts. */
3139 : :
3140 : 16008 : Dwarf_Die vardie = *scope_die, typedie;
3141 [ + - ][ - + ]: 16008 : if (dwarf_attr_die (&vardie, DW_AT_type, &typedie) == NULL)
3142 [ # # ][ # # ]: 0 : throw semantic_error(_F("failed to retrieve return value type attribute for %s [man error::dwarf] (%s)",
3143 : : (dwarf_diename(&vardie) ?: "<unknown>"),
3144 [ # # ][ # # ]: 0 : (dwarf_diename(cu) ?: "<unknown>")), e->tok);
[ # # ][ # # ]
3145 : :
3146 [ + + ]: 16008 : translate_components (&pool, &tail, pc, e, &vardie, &typedie);
3147 : :
3148 : : /* Translate the assignment part, either
3149 : : x = $return->bar->baz[NN]
3150 : : or
3151 : : $return->bar->baz[NN] = x
3152 : : */
3153 : :
3154 [ + - ][ + - ]: 16006 : string prelude, postlude;
3155 : : translate_final_fetch_or_store (&pool, &tail, module_bias,
3156 : : &vardie, &typedie, lvalue, e,
3157 [ + + ]: 16006 : prelude, postlude, ty);
3158 : :
3159 : : /* Write the translation to a string. */
3160 [ + - ][ + - ]: 16001 : string result = express_as_string(prelude, postlude, head);
[ + - ][ + - ]
[ + - ]
3161 [ - + ][ # # ]: 16001 : obstack_free (&pool, 0);
[ + - ]
3162 [ + - ][ + - ]: 16240 : return result;
3163 : : }
3164 : :
3165 : : Dwarf_Die*
3166 : 0 : dwflpp::type_die_for_return (Dwarf_Die *scope_die,
3167 : : Dwarf_Addr pc,
3168 : : const target_symbol *e,
3169 : : Dwarf_Die *typedie)
3170 : : {
3171 : 0 : Dwarf_Die vardie = *scope_die;
3172 [ # # ][ # # ]: 0 : if (dwarf_attr_die (&vardie, DW_AT_type, typedie) == NULL)
3173 [ # # ][ # # ]: 0 : throw semantic_error(_F("failed to retrieve return value type attribute for %s [man error::dwarf] (%s)",
3174 : : (dwarf_diename(&vardie) ?: "<unknown>"),
3175 [ # # ][ # # ]: 0 : (dwarf_diename(cu) ?: "<unknown>")), e->tok);
[ # # ][ # # ]
3176 : :
3177 [ # # ]: 0 : translate_components (NULL, NULL, pc, e, &vardie, typedie);
3178 : 0 : return typedie;
3179 : : }
3180 : :
3181 : :
3182 : : string
3183 : 17445 : dwflpp::literal_stmt_for_pointer (Dwarf_Die *start_typedie,
3184 : : const target_symbol *e,
3185 : : bool lvalue,
3186 : : exp_type & ty)
3187 : : {
3188 [ - + ]: 17445 : if (sess.verbose>2)
3189 [ # # ][ # # ]: 0 : clog << _F("literal_stmt_for_pointer: finding value for %s (%s)\n",
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
3190 [ # # ]: 0 : dwarf_type_name(start_typedie).c_str(), (dwarf_diename(cu) ?: "<unknown>"));
3191 : :
3192 : : struct obstack pool;
3193 [ + - ]: 17445 : obstack_init (&pool);
3194 : : struct location *head = c_translate_argument (&pool, &loc2c_error, this,
3195 : : &loc2c_emit_address,
3196 [ + - ]: 17445 : 1, "STAP_ARG_pointer");
3197 : 17445 : struct location *tail = head;
3198 : :
3199 : : /* Translate the ->bar->baz[NN] parts. */
3200 : :
3201 : 17445 : unsigned first = 0;
3202 : 17445 : Dwarf_Die typedie = *start_typedie, vardie = typedie;
3203 : :
3204 : : /* As a special case when typedie is not an array or pointer, we can
3205 : : * allow array indexing on STAP_ARG_pointer instead (since we do
3206 : : * know the pointee type and can determine its size). PR11556. */
3207 : : const target_symbol::component* c =
3208 [ + - ][ + + ]: 17445 : e->components.empty() ? NULL : &e->components[0];
3209 [ + + ][ + + ]: 17445 : if (c && (c->type == target_symbol::comp_literal_array_index ||
[ + + ]
3210 : : c->type == target_symbol::comp_expression_array_index))
3211 : : {
3212 [ + - ]: 214 : resolve_unqualified_inner_typedie (&typedie, &typedie, e);
3213 [ + - ]: 214 : int typetag = dwarf_tag (&typedie);
3214 [ + - ][ + - ]: 214 : if (typetag != DW_TAG_pointer_type &&
3215 : : typetag != DW_TAG_array_type)
3216 : : {
3217 [ + + ]: 214 : if (c->type == target_symbol::comp_literal_array_index)
3218 [ + - ]: 196 : c_translate_array_pointer (&pool, 1, &typedie, &tail, NULL, c->num_index);
3219 : : else
3220 [ + - ]: 18 : c_translate_array_pointer (&pool, 1, &typedie, &tail, "STAP_ARG_index0", 0);
3221 : 214 : ++first;
3222 : : }
3223 : : }
3224 : :
3225 : : /* Now translate the rest normally. */
3226 : :
3227 [ + + ]: 17445 : translate_components (&pool, &tail, 0, e, &vardie, &typedie, first);
3228 : :
3229 : : /* Translate the assignment part, either
3230 : : x = (STAP_ARG_pointer)->bar->baz[NN]
3231 : : or
3232 : : (STAP_ARG_pointer)->bar->baz[NN] = x
3233 : : */
3234 : :
3235 [ + - ][ + - ]: 16116 : string prelude, postlude;
3236 : : translate_final_fetch_or_store (&pool, &tail, module_bias,
3237 : : &vardie, &typedie, lvalue, e,
3238 [ + + ]: 16116 : prelude, postlude, ty);
3239 : :
3240 : : /* Write the translation to a string. */
3241 [ + - ][ + - ]: 16112 : string result = express_as_string(prelude, postlude, head);
[ + - ][ + - ]
[ + - ]
3242 [ - + ][ # # ]: 16112 : obstack_free (&pool, 0);
[ + - ]
3243 [ + - ][ + - ]: 17445 : return result;
3244 : : }
3245 : :
3246 : : Dwarf_Die*
3247 : 888 : dwflpp::type_die_for_pointer (Dwarf_Die *start_typedie,
3248 : : const target_symbol *e,
3249 : : Dwarf_Die *typedie)
3250 : : {
3251 : 888 : unsigned first = 0;
3252 : 888 : *typedie = *start_typedie;
3253 : 888 : Dwarf_Die vardie = *typedie;
3254 : :
3255 : : /* Handle the same PR11556 case as above. */
3256 : : const target_symbol::component* c =
3257 [ + - ][ + + ]: 888 : e->components.empty() ? NULL : &e->components[0];
3258 [ + + ][ + - ]: 888 : if (c && (c->type == target_symbol::comp_literal_array_index ||
[ - + ]
3259 : : c->type == target_symbol::comp_expression_array_index))
3260 : : {
3261 [ # # ]: 0 : resolve_unqualified_inner_typedie (typedie, typedie, e);
3262 [ # # ]: 0 : int typetag = dwarf_tag (typedie);
3263 [ # # ][ # # ]: 0 : if (typetag != DW_TAG_pointer_type &&
3264 : : typetag != DW_TAG_array_type)
3265 : 0 : ++first;
3266 : : }
3267 : :
3268 [ + - ]: 888 : translate_components (NULL, NULL, 0, e, &vardie, typedie, first);
3269 : 888 : return typedie;
3270 : : }
3271 : :
3272 : :
3273 : : static bool
3274 : 293180 : in_kprobes_function(systemtap_session& sess, Dwarf_Addr addr)
3275 : : {
3276 [ + - ][ + - ]: 293180 : if (sess.sym_kprobes_text_start != 0 && sess.sym_kprobes_text_end != 0)
3277 : : {
3278 : : // If the probe point address is anywhere in the __kprobes
3279 : : // address range, we can't use this probe point.
3280 [ + + ][ + + ]: 293180 : if (addr >= sess.sym_kprobes_text_start && addr < sess.sym_kprobes_text_end)
3281 : 1407 : return true;
3282 : : }
3283 : 293180 : return false;
3284 : : }
3285 : :
3286 : :
3287 : : bool
3288 : 377321 : dwflpp::blacklisted_p(const string& funcname,
3289 : : const string& filename,
3290 : : int,
3291 : : const string& module,
3292 : : Dwarf_Addr addr,
3293 : : bool has_return)
3294 : : {
3295 [ + + ]: 377321 : if (!blacklist_enabled)
3296 : 11813 : return false; // no blacklist for userspace
3297 : :
3298 : 365508 : bool blacklisted = false;
3299 : :
3300 : : // check against section blacklist
3301 [ + - ]: 365508 : string section = get_blacklist_section(addr);
3302 : : // PR6503: modules don't need special init/exit treatment
3303 [ + - ][ + + ]: 365508 : if (module == TOK_KERNEL && !regexec (&blacklist_section, section.c_str(), 0, NULL, 0))
[ + - ][ + - ]
[ + + ][ + + ]
3304 : : {
3305 : 7836 : blacklisted = true;
3306 [ - + ]: 7836 : if (sess.verbose>1)
3307 [ # # ]: 0 : clog << _(" init/exit");
3308 : : }
3309 : :
3310 : : // Check for function marked '__kprobes'.
3311 [ + - ][ + + ]: 365508 : if (module == TOK_KERNEL && in_kprobes_function(sess, addr))
[ + + ][ + + ]
3312 : : {
3313 : 1407 : blacklisted = true;
3314 [ - + ]: 1407 : if (sess.verbose>1)
3315 [ # # ]: 0 : clog << _(" __kprobes");
3316 : : }
3317 : :
3318 : : // Check probe point against file/function blacklists.
3319 [ + - ][ + - ]: 365508 : int goodfn = regexec (&blacklist_func, funcname.c_str(), 0, NULL, 0);
3320 [ + + ]: 365508 : if (has_return)
3321 [ + + ][ + - ]: 48066 : goodfn = goodfn && regexec (&blacklist_func_ret, funcname.c_str(), 0, NULL, 0);
[ + - ][ + + ]
3322 [ + - ][ + - ]: 365508 : int goodfile = regexec (&blacklist_file, filename.c_str(), 0, NULL, 0);
3323 : :
3324 [ + + ][ + + ]: 365508 : if (! (goodfn && goodfile))
3325 : : {
3326 : 40092 : blacklisted = true;
3327 [ - + ]: 40092 : if (sess.verbose>1)
3328 [ # # ]: 0 : clog << _(" file/function blacklist");
3329 : : }
3330 : :
3331 [ + + ][ + + ]: 365508 : if (sess.guru_mode && blacklisted)
3332 : : {
3333 : 8 : blacklisted = false;
3334 [ - + ]: 8 : if (sess.verbose>1)
3335 [ # # ]: 0 : clog << _(" - not skipped (guru mode enabled)");
3336 : : }
3337 : :
3338 [ + + ][ - + ]: 365508 : if (blacklisted && sess.verbose>1)
3339 [ # # ]: 0 : clog << _(" - skipped");
3340 : :
3341 : : // This probe point is not blacklisted.
3342 [ + - ]: 377321 : return blacklisted;
3343 : : }
3344 : :
3345 : :
3346 : : void
3347 : 1054 : dwflpp::build_blacklist()
3348 : : {
3349 : : // We build up the regexps in these strings
3350 : :
3351 : : // Add ^ anchors at the front; $ will be added just before regcomp.
3352 : :
3353 [ + - ]: 1054 : string blfn = "^(";
3354 [ + - ]: 1054 : string blfn_ret = "^(";
3355 [ + - ]: 1054 : string blfile = "^(";
3356 [ + - ]: 1054 : string blsection = "^(";
3357 : :
3358 [ + - ]: 1054 : blsection += "\\.init\\."; // first alternative, no "|"
3359 [ + - ]: 1054 : blsection += "|\\.exit\\.";
3360 [ + - ]: 1054 : blsection += "|\\.devinit\\.";
3361 [ + - ]: 1054 : blsection += "|\\.devexit\\.";
3362 [ + - ]: 1054 : blsection += "|\\.cpuinit\\.";
3363 [ + - ]: 1054 : blsection += "|\\.cpuexit\\.";
3364 [ + - ]: 1054 : blsection += "|\\.meminit\\.";
3365 [ + - ]: 1054 : blsection += "|\\.memexit\\.";
3366 : :
3367 : : /* NOTE all include/asm .h blfile patterns might need "full path"
3368 : : so prefix those with '.*' - see PR13108 and PR13112. */
3369 [ + - ]: 1054 : blfile += "kernel/kprobes\\.c"; // first alternative, no "|"
3370 [ + - ]: 1054 : blfile += "|arch/.*/kernel/kprobes\\.c";
3371 [ + - ]: 1054 : blfile += "|.*/include/asm/io\\.h";
3372 [ + - ]: 1054 : blfile += "|.*/include/asm/io_64\\.h";
3373 [ + - ]: 1054 : blfile += "|.*/include/asm/bitops\\.h";
3374 [ + - ]: 1054 : blfile += "|drivers/ide/ide-iops\\.c";
3375 : : // paravirt ops
3376 [ + - ]: 1054 : blfile += "|arch/.*/kernel/paravirt\\.c";
3377 [ + - ]: 1054 : blfile += "|.*/include/asm/paravirt\\.h";
3378 : :
3379 : : // XXX: it would be nice if these blacklisted functions were pulled
3380 : : // in dynamically, instead of being statically defined here.
3381 : : // Perhaps it could be populated from script files. A "noprobe
3382 : : // kernel.function("...")" construct might do the trick.
3383 : :
3384 : : // Most of these are marked __kprobes in newer kernels. We list
3385 : : // them here (anyway) so the translator can block them on older
3386 : : // kernels that don't have the __kprobes function decorator. This
3387 : : // also allows detection of problems at translate- rather than
3388 : : // run-time.
3389 : :
3390 [ + - ]: 1054 : blfn += "atomic_notifier_call_chain"; // first blfn; no "|"
3391 [ + - ]: 1054 : blfn += "|default_do_nmi";
3392 [ + - ]: 1054 : blfn += "|__die";
3393 [ + - ]: 1054 : blfn += "|die_nmi";
3394 [ + - ]: 1054 : blfn += "|do_debug";
3395 [ + - ]: 1054 : blfn += "|do_general_protection";
3396 [ + - ]: 1054 : blfn += "|do_int3";
3397 [ + - ]: 1054 : blfn += "|do_IRQ";
3398 [ + - ]: 1054 : blfn += "|do_page_fault";
3399 [ + - ]: 1054 : blfn += "|do_sparc64_fault";
3400 [ + - ]: 1054 : blfn += "|do_trap";
3401 [ + - ]: 1054 : blfn += "|dummy_nmi_callback";
3402 [ + - ]: 1054 : blfn += "|flush_icache_range";
3403 [ + - ]: 1054 : blfn += "|ia64_bad_break";
3404 [ + - ]: 1054 : blfn += "|ia64_do_page_fault";
3405 [ + - ]: 1054 : blfn += "|ia64_fault";
3406 [ + - ]: 1054 : blfn += "|io_check_error";
3407 [ + - ]: 1054 : blfn += "|mem_parity_error";
3408 [ + - ]: 1054 : blfn += "|nmi_watchdog_tick";
3409 [ + - ]: 1054 : blfn += "|notifier_call_chain";
3410 [ + - ]: 1054 : blfn += "|oops_begin";
3411 [ + - ]: 1054 : blfn += "|oops_end";
3412 [ + - ]: 1054 : blfn += "|program_check_exception";
3413 [ + - ]: 1054 : blfn += "|single_step_exception";
3414 [ + - ]: 1054 : blfn += "|sync_regs";
3415 [ + - ]: 1054 : blfn += "|unhandled_fault";
3416 [ + - ]: 1054 : blfn += "|unknown_nmi_error";
3417 [ + - ]: 1054 : blfn += "|xen_[gs]et_debugreg";
3418 [ + - ]: 1054 : blfn += "|xen_irq_.*";
3419 [ + - ]: 1054 : blfn += "|xen_.*_fl_direct.*";
3420 [ + - ]: 1054 : blfn += "|check_events";
3421 [ + - ]: 1054 : blfn += "|xen_adjust_exception_frame";
3422 [ + - ]: 1054 : blfn += "|xen_iret.*";
3423 [ + - ]: 1054 : blfn += "|xen_sysret64.*";
3424 [ + - ]: 1054 : blfn += "|test_ti_thread_flag.*";
3425 [ + - ]: 1054 : blfn += "|inat_get_opcode_attribute";
3426 [ + - ]: 1054 : blfn += "|system_call_after_swapgs";
3427 [ + - ]: 1054 : blfn += "|HYPERVISOR_[gs]et_debugreg";
3428 [ + - ]: 1054 : blfn += "|HYPERVISOR_event_channel_op";
3429 [ + - ]: 1054 : blfn += "|hash_64";
3430 [ + - ]: 1054 : blfn += "|hash_ptr";
3431 [ + - ]: 1054 : blfn += "|native_set_pte";
3432 : :
3433 : : // Lots of locks
3434 [ + - ]: 1054 : blfn += "|.*raw_.*_lock.*";
3435 [ + - ]: 1054 : blfn += "|.*raw_.*_unlock.*";
3436 [ + - ]: 1054 : blfn += "|.*raw_.*_trylock.*";
3437 [ + - ]: 1054 : blfn += "|.*read_lock.*";
3438 [ + - ]: 1054 : blfn += "|.*read_unlock.*";
3439 [ + - ]: 1054 : blfn += "|.*read_trylock.*";
3440 [ + - ]: 1054 : blfn += "|.*write_lock.*";
3441 [ + - ]: 1054 : blfn += "|.*write_unlock.*";
3442 [ + - ]: 1054 : blfn += "|.*write_trylock.*";
3443 [ + - ]: 1054 : blfn += "|.*write_seqlock.*";
3444 [ + - ]: 1054 : blfn += "|.*write_sequnlock.*";
3445 [ + - ]: 1054 : blfn += "|.*spin_lock.*";
3446 [ + - ]: 1054 : blfn += "|.*spin_unlock.*";
3447 [ + - ]: 1054 : blfn += "|.*spin_trylock.*";
3448 [ + - ]: 1054 : blfn += "|.*spin_is_locked.*";
3449 [ + - ]: 1054 : blfn += "|rwsem_.*lock.*";
3450 [ + - ]: 1054 : blfn += "|.*mutex_.*lock.*";
3451 [ + - ]: 1054 : blfn += "|raw_.*";
3452 : :
3453 : : // atomic functions
3454 [ + - ]: 1054 : blfn += "|atomic_.*";
3455 [ + - ]: 1054 : blfn += "|atomic64_.*";
3456 : :
3457 : : // few other problematic cases
3458 [ + - ]: 1054 : blfn += "|get_bh";
3459 [ + - ]: 1054 : blfn += "|put_bh";
3460 : :
3461 : : // Experimental
3462 [ + - ]: 1054 : blfn += "|.*apic.*|.*APIC.*";
3463 [ + - ]: 1054 : blfn += "|.*softirq.*";
3464 [ + - ]: 1054 : blfn += "|.*IRQ.*";
3465 [ + - ]: 1054 : blfn += "|.*_intr.*";
3466 [ + - ]: 1054 : blfn += "|__delay";
3467 [ + - ]: 1054 : blfn += "|.*kernel_text.*";
3468 [ + - ]: 1054 : blfn += "|get_current";
3469 [ + - ]: 1054 : blfn += "|current_.*";
3470 [ + - ]: 1054 : blfn += "|.*exception_tables.*";
3471 [ + - ]: 1054 : blfn += "|.*setup_rt_frame.*";
3472 : :
3473 : : // PR 5759, CONFIG_PREEMPT kernels
3474 [ + - ]: 1054 : blfn += "|.*preempt_count.*";
3475 [ + - ]: 1054 : blfn += "|preempt_schedule";
3476 : :
3477 : : // These functions don't return, so return probes would never be recovered
3478 [ + - ]: 1054 : blfn_ret += "do_exit"; // no "|"
3479 [ + - ]: 1054 : blfn_ret += "|sys_exit";
3480 [ + - ]: 1054 : blfn_ret += "|sys_exit_group";
3481 : :
3482 : : // __switch_to changes "current" on x86_64 and i686, so return probes
3483 : : // would cause kernel panic, and it is marked as "__kprobes" on x86_64
3484 [ + - ][ - + ]: 1054 : if (sess.architecture == "x86_64")
3485 [ # # ]: 0 : blfn += "|__switch_to";
3486 [ + - ][ - + ]: 1054 : if (sess.architecture == "i686")
3487 [ # # ]: 0 : blfn_ret += "|__switch_to";
3488 : :
3489 : : // RHEL6 pre-beta 2.6.32-19.el6
3490 [ + - ]: 1054 : blfn += "|special_mapping_.*";
3491 [ + - ]: 1054 : blfn += "|.*_pte_.*"; // or "|smaps_pte_range";
3492 [ + - ]: 1054 : blfile += "|fs/seq_file\\.c";
3493 : :
3494 [ + - ]: 1054 : blfn += ")$";
3495 [ + - ]: 1054 : blfn_ret += ")$";
3496 [ + - ]: 1054 : blfile += ")$";
3497 [ + - ]: 1054 : blsection += ")"; // NB: no $, sections match just the beginning
3498 : :
3499 [ - + ]: 1054 : if (sess.verbose > 2)
3500 : : {
3501 [ # # ][ # # ]: 0 : clog << _("blacklist regexps:") << endl;
3502 [ # # ][ # # ]: 0 : clog << "blfn: " << blfn << endl;
[ # # ]
3503 [ # # ][ # # ]: 0 : clog << "blfn_ret: " << blfn_ret << endl;
[ # # ]
3504 [ # # ][ # # ]: 0 : clog << "blfile: " << blfile << endl;
[ # # ]
3505 [ # # ][ # # ]: 0 : clog << "blsection: " << blsection << endl;
[ # # ]
3506 : : }
3507 : :
3508 [ + - ][ + - ]: 1054 : int rc = regcomp (& blacklist_func, blfn.c_str(), REG_NOSUB|REG_EXTENDED);
3509 [ - + ][ # # ]: 1054 : if (rc) throw semantic_error (_("blacklist_func regcomp failed"));
[ # # ]
3510 [ + - ][ + - ]: 1054 : rc = regcomp (& blacklist_func_ret, blfn_ret.c_str(), REG_NOSUB|REG_EXTENDED);
3511 [ - + ][ # # ]: 1054 : if (rc) throw semantic_error (_("blacklist_func_ret regcomp failed"));
[ # # ]
3512 [ + - ][ + - ]: 1054 : rc = regcomp (& blacklist_file, blfile.c_str(), REG_NOSUB|REG_EXTENDED);
3513 [ - + ][ # # ]: 1054 : if (rc) throw semantic_error (_("blacklist_file regcomp failed"));
[ # # ]
3514 [ + - ][ + - ]: 1054 : rc = regcomp (& blacklist_section, blsection.c_str(), REG_NOSUB|REG_EXTENDED);
3515 [ - + ][ # # ]: 1054 : if (rc) throw semantic_error (_("blacklist_section regcomp failed"));
[ # # ]
3516 : :
3517 [ + - ][ + - ]: 1054 : blacklist_enabled = true;
[ + - ][ + - ]
3518 : 1054 : }
3519 : :
3520 : :
3521 : : string
3522 : 365508 : dwflpp::get_blacklist_section(Dwarf_Addr addr)
3523 : : {
3524 [ + - ]: 365508 : string blacklist_section;
3525 : : Dwarf_Addr bias;
3526 : : // We prefer dwfl_module_getdwarf to dwfl_module_getelf here,
3527 : : // because dwfl_module_getelf can force costly section relocations
3528 : : // we don't really need, while either will do for this purpose.
3529 [ + - ][ + - ]: 365508 : Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (module, &bias))
3530 [ + - ][ # # ]: 365508 : ?: dwfl_module_getelf (module, &bias));
3531 : :
3532 : 365508 : Dwarf_Addr offset = addr - bias;
3533 [ + - ]: 365508 : if (elf)
3534 : : {
3535 : 365508 : Elf_Scn* scn = 0;
3536 : : size_t shstrndx;
3537 [ + - ][ + - ]: 365508 : dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx));
[ + - ][ + - ]
3538 [ + - ][ + - ]: 1115501 : while ((scn = elf_nextscn (elf, scn)) != NULL)
3539 : : {
3540 : : GElf_Shdr shdr_mem;
3541 [ + - ]: 749993 : GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
3542 [ - + ]: 749993 : if (! shdr)
3543 : 0 : continue; // XXX error?
3544 : :
3545 [ + + ]: 749993 : if (!(shdr->sh_flags & SHF_ALLOC))
3546 : 2191 : continue;
3547 : :
3548 : 747802 : GElf_Addr start = shdr->sh_addr;
3549 : 747802 : GElf_Addr end = start + shdr->sh_size;
3550 [ + - ][ + + ]: 747802 : if (! (offset >= start && offset < end))
3551 : 382294 : continue;
3552 : :
3553 [ + - ][ + - ]: 749993 : blacklist_section = elf_strptr (elf, shstrndx, shdr->sh_name);
3554 : : break;
3555 : : }
3556 : : }
3557 : 365508 : return blacklist_section;
3558 : : }
3559 : :
3560 : :
3561 : : /* Find the section named 'section_name' in the current module
3562 : : * returning the section header using 'shdr_mem' */
3563 : :
3564 : : GElf_Shdr *
3565 : 23 : dwflpp::get_section(string section_name, GElf_Shdr *shdr_mem, Elf **elf_ret)
3566 : : {
3567 : 23 : GElf_Shdr *shdr = NULL;
3568 : : Elf* elf;
3569 : : Dwarf_Addr bias;
3570 : : size_t shstrndx;
3571 : :
3572 : : // Explicitly look in the main elf file first.
3573 [ + - ]: 23 : elf = dwfl_module_getelf (module, &bias);
3574 : 23 : Elf_Scn *probe_scn = NULL;
3575 : :
3576 [ + - ][ + - ]: 23 : dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx));
[ + - ][ + - ]
3577 : :
3578 : 23 : bool have_section = false;
3579 : :
3580 [ + - ][ + + ]: 822 : while ((probe_scn = elf_nextscn (elf, probe_scn)))
3581 : : {
3582 [ + - ]: 805 : shdr = gelf_getshdr (probe_scn, shdr_mem);
3583 [ - + ]: 805 : assert (shdr != NULL);
3584 : :
3585 [ + - ][ + - ]: 805 : if (elf_strptr (elf, shstrndx, shdr->sh_name) == section_name)
[ + + ]
3586 : : {
3587 : 6 : have_section = true;
3588 : 6 : break;
3589 : : }
3590 : : }
3591 : :
3592 : : // Older versions may put the section in the debuginfo dwarf file,
3593 : : // so check if it actually exists, if not take a look in the debuginfo file
3594 [ + + ][ + - ]: 23 : if (! have_section || (have_section && shdr->sh_type == SHT_NOBITS))
[ - + ]
3595 : : {
3596 [ + - ][ + - ]: 17 : elf = dwarf_getelf (dwfl_module_getdwarf (module, &bias));
3597 [ + + ]: 17 : if (! elf)
3598 : 14 : return NULL;
3599 [ + - ][ + - ]: 3 : dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx));
[ + - ][ + - ]
3600 : 3 : probe_scn = NULL;
3601 [ + - ][ + + ]: 126 : while ((probe_scn = elf_nextscn (elf, probe_scn)))
3602 : : {
3603 [ + - ]: 123 : shdr = gelf_getshdr (probe_scn, shdr_mem);
3604 [ + - ][ + - ]: 123 : if (elf_strptr (elf, shstrndx, shdr->sh_name) == section_name)
[ - + ]
3605 : : {
3606 : 0 : have_section = true;
3607 : 0 : break;
3608 : : }
3609 : : }
3610 : : }
3611 : :
3612 [ + + ]: 9 : if (!have_section)
3613 : 3 : return NULL;
3614 : :
3615 [ - + ]: 6 : if (elf_ret)
3616 : 0 : *elf_ret = elf;
3617 : 23 : return shdr;
3618 : : }
3619 : :
3620 : :
3621 : : Dwarf_Addr
3622 : 377321 : dwflpp::relocate_address(Dwarf_Addr dw_addr, string& reloc_section)
3623 : : {
3624 : : // PR10273
3625 : : // libdw address, so adjust for bias gotten from dwfl_module_getdwarf
3626 : 377321 : Dwarf_Addr reloc_addr = dw_addr + module_bias;
3627 [ - + ]: 377321 : if (!module)
3628 : : {
3629 [ # # ][ # # ]: 0 : assert(module_name == TOK_KERNEL);
3630 [ # # ]: 0 : reloc_section = "";
3631 : : }
3632 [ + - ][ + + ]: 377321 : else if (dwfl_module_relocations (module) > 0)
3633 : : {
3634 : : // This is a relocatable module; libdwfl already knows its
3635 : : // sections, so we can relativize addr.
3636 [ + - ]: 365508 : int idx = dwfl_module_relocate_address (module, &reloc_addr);
3637 [ + - ]: 365508 : const char* r_s = dwfl_module_relocation_info (module, idx, NULL);
3638 [ + - ]: 365508 : if (r_s)
3639 [ + - ]: 365508 : reloc_section = r_s;
3640 : :
3641 [ + - ][ + + ]: 365508 : if (reloc_section == "" && dwfl_module_relocations (module) == 1)
[ + - ][ + - ]
[ + + ]
3642 [ + - ]: 293180 : reloc_section = ".dynamic";
3643 : : }
3644 : : else
3645 [ + - ]: 11813 : reloc_section = ".absolute";
3646 : 377321 : return reloc_addr;
3647 : : }
3648 : :
3649 : : /* Returns the call frame address operations for the given program counter
3650 : : * in the libdw address space.
3651 : : */
3652 : : Dwarf_Op *
3653 : 224574 : dwflpp::get_cfa_ops (Dwarf_Addr pc)
3654 : : {
3655 : 224574 : Dwarf_Op *cfa_ops = NULL;
3656 : :
3657 [ - + ]: 224574 : if (sess.verbose > 2)
3658 [ # # ][ # # ]: 0 : clog << "get_cfa_ops @0x" << hex << pc << dec
[ # # ][ # # ]
3659 [ # # ][ # # ]: 0 : << ", module_start @0x" << hex << module_start << dec << endl;
[ # # ][ # # ]
[ # # ]
3660 : :
3661 : : // Try debug_frame first, then fall back on eh_frame.
3662 : 224574 : size_t cfa_nops = 0;
3663 : 224574 : Dwarf_Addr bias = 0;
3664 : 224574 : Dwarf_Frame *frame = NULL;
3665 [ + - ]: 224574 : Dwarf_CFI *cfi = dwfl_module_dwarf_cfi (module, &bias);
3666 [ + + ]: 224574 : if (cfi != NULL)
3667 : : {
3668 [ - + ]: 219914 : if (sess.verbose > 3)
3669 [ # # ][ # # ]: 0 : clog << "got dwarf cfi bias: 0x" << hex << bias << dec << endl;
[ # # ][ # # ]
[ # # ]
3670 [ + - ][ + + ]: 219914 : if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0)
3671 [ + - ]: 199093 : dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
3672 [ - + ]: 20821 : else if (sess.verbose > 3)
3673 [ # # ][ # # ]: 0 : clog << "dwarf_cfi_addrframe failed: " << dwarf_errmsg(-1) << endl;
[ # # ][ # # ]
3674 : : }
3675 [ - + ]: 4660 : else if (sess.verbose > 3)
3676 [ # # ][ # # ]: 0 : clog << "dwfl_module_dwarf_cfi failed: " << dwfl_errmsg(-1) << endl;
[ # # ][ # # ]
3677 : :
3678 [ + + ]: 224574 : if (cfa_ops == NULL)
3679 : : {
3680 [ + - ]: 25481 : cfi = dwfl_module_eh_cfi (module, &bias);
3681 [ + + ]: 25481 : if (cfi != NULL)
3682 : : {
3683 [ - + ]: 13 : if (sess.verbose > 3)
3684 [ # # ][ # # ]: 0 : clog << "got eh cfi bias: 0x" << hex << bias << dec << endl;
[ # # ][ # # ]
[ # # ]
3685 : 13 : Dwarf_Frame *frame = NULL;
3686 [ + - ][ - + ]: 13 : if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0)
3687 [ # # ]: 0 : dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
3688 [ - + ]: 13 : else if (sess.verbose > 3)
3689 [ # # ][ # # ]: 13 : clog << "dwarf_cfi_addrframe failed: " << dwarf_errmsg(-1) << endl;
[ # # ][ # # ]
3690 : : }
3691 [ - + ]: 25468 : else if (sess.verbose > 3)
3692 [ # # ][ # # ]: 0 : clog << "dwfl_module_eh_cfi failed: " << dwfl_errmsg(-1) << endl;
[ # # ][ # # ]
3693 : :
3694 : : }
3695 : :
3696 [ - + ]: 224574 : if (sess.verbose > 2)
3697 : : {
3698 [ # # ]: 0 : if (cfa_ops == NULL)
3699 [ # # ][ # # ]: 0 : clog << _("not found cfa") << endl;
3700 : : else
3701 : : {
3702 : : Dwarf_Addr frame_start, frame_end;
3703 : : bool frame_signalp;
3704 : : int info = dwarf_frame_info (frame, &frame_start, &frame_end,
3705 [ # # ]: 0 : &frame_signalp);
3706 [ # # ][ # # ]: 0 : clog << _F("found cfa, info: %d [start: %#" PRIx64 ", end: %#" PRIx64
[ # # ]
3707 [ # # ]: 0 : ", nops: %zu", info, frame_start, frame_end, cfa_nops) << endl;
3708 : : }
3709 : : }
3710 : :
3711 : 224574 : return cfa_ops;
3712 : : }
3713 : :
3714 : : int
3715 : 1831 : dwflpp::add_module_build_id_to_hash (Dwfl_Module *m,
3716 : : void **userdata __attribute__ ((unused)),
3717 : : const char *name,
3718 : : Dwarf_Addr base,
3719 : : void *arg)
3720 : : {
3721 [ + - ]: 1831 : string modname = name;
3722 : 1831 : systemtap_session * s = (systemtap_session *)arg;
3723 [ - + ]: 1831 : if (pending_interrupts)
3724 : 0 : return DWARF_CB_ABORT;
3725 : :
3726 : : // Extract the build ID
3727 : : const unsigned char *bits;
3728 : : GElf_Addr vaddr;
3729 [ + - ]: 1831 : int bits_length = dwfl_module_build_id(m, &bits, &vaddr);
3730 [ + - ]: 1831 : if(bits_length > 0)
3731 : : {
3732 : : // Convert the binary bits to a hex string
3733 [ + - ]: 1831 : string hex = hex_dump(bits, bits_length);
3734 : :
3735 : : // Store the build ID in the session
3736 [ + - ][ + - ]: 1831 : s->build_ids.push_back(hex);
3737 : : }
3738 : :
3739 [ + - ]: 1831 : return DWARF_CB_OK;
3740 : : }
3741 : :
3742 : :
3743 : :
3744 : : // Perform PR15123 heuristic for given variable at given address.
3745 : : // Return alternate pc address to do location-list lookup at, or 0 if
3746 : : // inapplicable.
3747 : : //
3748 : : Dwarf_Addr
3749 : 25783 : dwflpp::pr15123_retry_addr (Dwarf_Addr pc, Dwarf_Die* die)
3750 : : {
3751 : : // For PR15123, we'd like to detect the situation where the
3752 : : // incoming PC may point to a couple-of-byte instruction
3753 : : // sequence that gcc emits for CFLAGS=-mfentry, and where
3754 : : // context variables are in fact available throughout, *but* due
3755 : : // to the bug, the dwarf debuginfo location-list only starts a
3756 : : // few instructions later. Prologue searching does not resolve
3757 : : // this as a line-record is in place at the -mfentry prologue.
3758 : : //
3759 : : // Detecting this is complicated because ...
3760 : : // - we only want to do this if -mfentry was actually used
3761 : : // - if <pc> points to the a function entry point
3762 : : // - if the architecture is familiar enough that we can have a
3763 : : // hard-coded constant to skip over the prologue.
3764 : : //
3765 : : // Otherwise, we could give a false-positive - return corrupted data.
3766 : :
3767 [ - + ]: 25783 : if (getenv ("PR15123_DISABLE"))
3768 : 0 : return 0;
3769 : :
3770 : : Dwarf_Die cudie;
3771 : : Dwarf_Attribute cudie_producer;
3772 [ + - ]: 25783 : dwarf_diecu (die, &cudie, NULL, NULL);
3773 [ + - ][ - + ]: 25783 : if (! dwarf_attr_integrate(&cudie, DW_AT_producer, &cudie_producer))
3774 : 0 : return 0;
3775 : :
3776 [ + - ]: 25783 : const char* producer = dwarf_formstring(&cudie_producer);
3777 [ - + ]: 25783 : if (!producer)
3778 : 0 : return 0;
3779 [ + - ]: 25783 : if (! strstr(producer, "-mfentry"))
3780 : 25783 : return 0;
3781 : :
3782 : : // Determine if this pc maps to the beginning of a
3783 : : // real function (not some inlined doppelganger. This
3784 : : // is made tricker by this->function may not be
3785 : : // pointing at the right DIE (say e.g. stap encountered
3786 : : // the inlined copy first, so was focus_on_function'd).
3787 [ # # ]: 0 : vector<Dwarf_Die> scopes = getscopes(pc);
3788 [ # # ]: 0 : if (scopes.size() == 0)
3789 : 0 : return 0;
3790 : :
3791 : 0 : Dwarf_Die outer_function_die = scopes[0];
3792 : : Dwarf_Addr entrypc;
3793 [ # # ]: 0 : die_entrypc(& outer_function_die, &entrypc);
3794 [ # # ]: 0 : if (entrypc != pc) // (will fail on retry, so we won't loop more than once)
3795 : 0 : return 0;
3796 : :
3797 [ # # ][ # # ]: 0 : if (sess.architecture == "i386" ||
[ # # ][ # # ]
3798 [ # # ]: 0 : sess.architecture == "x86_64") {
3799 : : /* pull the trigger */
3800 [ # # ]: 0 : if (sess.verbose > 2)
3801 [ # # ]: 0 : clog << _("retrying variable location-list lookup at address pc+5\n");
3802 : 0 : return pc + 5;
3803 : : }
3804 : :
3805 [ # # ]: 25783 : return 0;
3806 [ + - ][ + - ]: 7242 : }
3807 : :
3808 : :
3809 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|