| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
| |
* setupdwfl.h: Introduce DwflPtr.
* setupdwfl.cxx: Cache kernel_dwfl and user_dwfl. Keep track of last used
module strings. Return cached versions if same query used.
* dwflpp.h: Use DwflPtr instead of Dwfl*.
* dwflpp.cxx: Use DwflPtr and don't dwfl_end().
* translate.cxx: Likewise. Run through dwfl_getmodules() with returned
ptr offset.
|
|
|
|
|
|
|
|
|
|
|
| |
Tracepoint modules ended up going through dwflpp::setup_user() because
there was no setup_kernel that takes a list of module names.
* dwflpp.h: Add kernel_p bool to constructor that takes a module list.
Add setup_kernel() variant that takes a module list.
* dwflpp.cxx: Likewise.
* tapsets.cxx (tracepoint_builder::init_dw): Call dwflpp constructor
indicating we expect kernel modules.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The function spec for dwarf probes now supports scopes, so you can limit
the probes to specific namespaces or classes. Multiple scopes can be
specified, and they will be matched progressively outward.
probe process("foo").function("std::vector<*>::*") { ... }
probe process("foo").function("::global_function") { ... }
* dwflpp.cxx (dwflpp::get_parent_scope): New, finds the containing
scopes of the specified DIE.
(dwflpp::function_scope_matches): New, checks that the scopes
containing the function all match the given scope patterns.
* tapsets.cxx (dwarf_query::parse_function_spec): Rewrite, now handles
multiple scope separators too.
(query_dwarf_func): Check that the functions scopes match.
|
|
|
|
| |
* dwflpp.cxx (dwflpp::function_name_final_match): Removed.
|
|
|
|
|
|
|
|
|
|
|
| |
We already have filtered functions and inlines, so just iterate in each
of those to look for labels.
* dwflpp.cxx (dwflpp::iterate_over_labels): Assume that the die we're
looking at is already a matching function, and don't descend into
inlined functions in this body.
* tapsets.cxx (query_srcfile_label): Iterate through inlines too.
(query_cu): Iterate over functions and inlines instead of the CU.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Variable lookup is usually done through the scopes from dwarf_getscopes
at a particular pc. This requires an expensive traversal to find the
inner-most die containing the pc. For cases where that containing die
is known, e.g. at a particular function entry, we can do much better
with our die_parent_cache.
This may also help get more accurate variable scopes in cases where
multiple dies contain a pc and the innermost isn't what we're trying to
probe. For example, an inlined call chain of foo->bar->baz may all have
the same entry pc, but if the probe was on function("bar"), we would
want the variables in bar's scope, not baz's.
* dwflpp.h (struct dwflpp): Remove pc_cached_scopes, num_cached_scopes,
and cached_scopes, as they are now remembered by the caller.
* dwflpp.cxx (dwflpp::getscopes): New - the DIE version uses the parent
cache, and the pc version just defers to dwarf_getscopes.
(dwflpp::print_locals, literal_stmt_for_local): Take a scopes vector.
(dwflpp::find_variable_and_frame_base): Take a scopes vector from the
caller instead of computing it every time.
(dwflpp::dwarf_getscopes_cached): Removed.
* tapsets.cxx (dwarf_var_expanding_visitor::getscopes): New cached
lookup function which gets the scopes from the DIE if possible.
(dwarf_var_expanding_visitor::visit_target_symbol): Call getscopes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This avoids repeated DIE traversal by caching all parents on the first
call, so future calls are just a simple walk up parent links.
* dwflpp.cxx (dwflpp::getscopes_die): New cached function that mimics
libdw's dwarf_getscopes_die using cached parent links.
(dwflpp::cache_die_parents): New function to build the parent cache.
(dwflpp::~dwflpp): Clean up the parent caches.
(dwflpp::iterate_over_labels): Use the cached getscopes_die.
(dwflpp::find_variable_and_frame_base): Ditto.
* tapsets.cxx (dwarf_derived_probe::saveargs): Ditto.
(uprobe_derived_probe::saveargs): Ditto.
(dwarf_var_expanding_visitor::visit_target_symbol_context): Ditto.
|
|
|
|
|
|
|
|
| |
We already use regexp for function/file blacklisting, so this just makes
the section blacklisting consistent with the rest.
* dwflpp.cxx (dwflpp::blacklisted_p): Use regexec instead of section==.
(dwflpp::build_blacklist): Build blacklist_section too.
|
|
|
|
|
|
|
|
|
|
| |
We only check blacklisting on kernel probes, so it's a waste to dig up
the section name otherwise.
* dwflpp.cxx (dwflpp::blacklisted_p): Lookup the section directly.
(relocate_address::relocate_address): Don't do blacklisting here.
* tapsets.cxx (dwarf_query::add_probe_point): Don't carry the blacklist
section directly anymore.
|
|
|
|
|
|
|
|
|
|
|
| |
In C++, identical functions included in multiple CUs will get merged at
link time into a single instance. We need to make sure that inlines
within those merged functions are not probed multiple times.
* tapsets.cxx (inline_instance_info::operator<): Used for set support.
(dwarf_query::handle_query_module): Clear inline_dupes on each module.
(query_dwarf_inline_instance): Squash this inline instance if it's
already in the inline_dupes set.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We can't assume that a given function name will only appear once in a
CU. In C++, two functions may have the same name in different classes
or namespaces, or even in the same scope with overloaded parameters.
Even in C, the compiler may generate multiple copies of a single
function with different optimizations.
We now use a multimap for function names, so we shouldn't miss any.
* dwflpp.h (cu_type_cache_t, mod_cu_type_cache_t): New typedef to keep a
normal map for the global_alias_cache.
(cu_function_cache_t): Use a multimap for function names.
* dwflpp.cxx (dwflpp::iterate_over_functions): Walk over the range of
exactly-matching functions.
* tapsets.cxx (query_dwarf_func): Don't abort after seeing an exact
match -- there could be more to come.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We were defining our own stap_map with a ::type to let us use typedefs
to use the new unordered_map if available, or hash_map otherwise. Since
unordered_map is the future direction, I'm changing our code to use that
directly. The backward-compatible version is a #define to hash_map,
which has a compatible interface.
While I'm at it, let's also define unordered_multimap, unordered_set,
and unordered_multiset.
* unordered.h: New.
* dwflpp.h (stap_map): Removed.
(cache typedefs): Use the unordered name now.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We used to call dwarf_func_inline_instances to get the locations where
inlines are used. This function has to iterate through nearly all DIEs
to find instances, which is a lot of redundant work when we're probing
multiple inline functions.
Now we have our own dwarf iterator to cache all inline instances back to
their origin. This only needs to be called once for each CU, and all
further inlines are just a map lookup. Some quick benchmarks:
stap -l Before After
kernel.function("*") 25010ms 2110ms
module("*").function("*") 86550ms 16920ms
process("stap").function("*") 41330ms 580ms
* dwflpp.cxx (dwflpp::cu_inl_function_caching_callback): Removed.
(dwflpp::cache_inline_instances): New caching iterator.
(dwflpp::iterate_over_inline_instances): Cache each CU once.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I noticed that iterate_over_labels was using a static variable as a
recursion variable, which isn't a safe thing to do since it will only be
initialized once. While fixing that, I also reorganized the function
quite a bit.
* dwflpp.cxx (dwflpp::iterate_over_labels): Take the current function as
a parameter instead of using a static local. Rewrite some of the code
as well to try to make it more obvious.
* tapsets.cxx (add_label_name): Remove in favor of query_label.
(query_label): New, to check decl_file and fix probe listing.
(query_srcfile_label, query_cu): Adjust to iterate_over_labels change
and start using query_label as the callback.
|
|
|
|
|
|
|
|
|
|
|
|
| |
We only need cu_name for errors and verbose messages, so it's a waste to
always construct it in focus_on_cu. It's now built only as-needed.
* dwflpp.cxx (dwflpp::cu_name): Now a method instead of a data member.
(dwflpp::focus_on_module): No cu_name to clear now.
(dwflpp::focus_on_cu): No cu_name to set now.
(dwflpp::declaration_resolve): Adjust to call cu_name() now.
(dwflpp::iterate_over_functions): Ditto.
* tapsets.cxx (query_cu): Ditto.
|
|
|
|
| |
* dwflpp.cxx (module_cu_cache_t): Typedef as a stap_map instead.
|
|
|
|
|
|
|
|
| |
Again, avoid needless string construction for map indexing.
* dwflpp.h (cu_inl_function_cache_t): Index by the void* function->addr.
* dwflpp.cxx (dwflpp::iterate_over_inline_instances): Index
cu_inl_function_cache by function->addr.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rather than constructing a "module:cu" string all the time, we can just
index the cache by the cu die's addr field. The addr will never change
as long as the Dwarf object is still alive.
This has a quite noticeable performance impact for scripts that iterate
over lots of cus (like for syscall.*).
* dwflpp.h (stap_map): Allow void* keys too.
(mod_cu_function_cache_t): Index by the void* cu->addr.
* dwflpp.cxx (dwflpp::iterate_over_functions): Index cu_function_cache
by addr, and build the verbose strings manually when needed.
(dwflpp::declaration_resolve): Index global_alias_cache by addr.
|
|
|
|
|
|
|
|
|
|
|
|
| |
We used to only check that a CU contains at least one srcfile matching
the user's file spec. This patch ensures that the selected function was
actually defined in one of the matching srcfiles.
* tapsets.cxx (struct dwarf_query): Make filtered_srcfiles carry
strings, so we can easily lookup matches later.
(query_dwarf_func): Check that the decl_file is in filtered_srcfiles.
(query_cu): Adjust to using set<string>.
* dwflpp.cxx (dwflpp::collect_srcfiles_matching): Take a set<string>.
|
|
|
|
|
|
|
| |
We were jumping through a few hoops to deal with elfutils < 0.138 that
did not have the _ELFUTILS_PREREQ macro. I've added an always-false
dummy macro to take its place when it doesn't exit. All of the other
"#ifdef _ELFUTILS_PREREQ" ugliness can now go away.
|
|
|
|
|
|
|
|
|
| |
* dwflpp.cxx (iterate_over_srcfile_lines): Add pattern parameter.
* dwflpp.h (iterate_over_srcfile_lines): Ditto.
* testsuite/systemtap.base/bz10294.c: Test case.
* testsuite/systemtap.base/bz10294.stp: Ditto.
* testsuite/systemtap.base/bz6905.exp: Deleted.
* testsuite/systemtap.base/statement.exp: Merge bz10294 with bz6905.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now the dereferences on target_symbol and cast_op are tracked with a
struct instead of just a generic pair. The first immediate benefit is
that we can track the token for more exact error reporting.
* staptree.h (target_symbol): Add a new component type.
* staptree.cxx (target_symbol::component::print): New.
(operator<<(ostream&, target_symbol::component&): New.
(target_symbol::print): Adapt component printing.
(cast_op::print): Ditto.
* parse.cxx (parser::parse_target_symbol_components): Adapt to the new
component construction.
* dwflpp.cxx (dwflpp::find_struct_member): take the component as a
parameter for a better token in error messages
(dwflpp::translate_components): Adapt to the new component type.
* tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Don't
overwrite the token in target_symbol saved errors.
(tracepoint_var_expanding_visitor::visit_target_symbol_arg): Ditto.
|
|
|
|
|
|
|
|
|
| |
This will be used to load tracepoint modules as a bunch of little query
modules into a single dwflpp.
* dwflpp.cxx (setup_user): take a vector instead of a single module
(dwflpp::dwflpp): form a vector in the singular case, and add a
variant that takes and passes through a vector of modules.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Depends on elfutils 0.142 cfi support.
* loc2c.h (c_translate_location): Take (optional) Dwarf_Op *cfa_ops.
* loc2c.c (translate): Recognize DW_OP_call_frame_cfa.
(location_from_address): Take cfa_ops, examine fb_ops, if it is
DW_OP_call_frame_cfa, pass cfa_ops to translate instead.
(location_relative): Take cfa_ops, pass to location_from_address.
(c_translate_location): Take cfa_ops, pass to location_from_address.
* loc2c-test.c (handle_variable): Take cfa_ops, pass to c_translate_location
when needed.
(main): Fetch cfa_ops, pass to handle_variable.
* dwflpp.h (struct dwflpp): Add new method get_cfa_ops.
* dwflpp.cxx: Include elfutils/version.h.
(translate_location): Fetch cfa_ops when necessary.
(get_cfa_ops): New method.
|
|
|
|
|
|
|
|
| |
* dwflpp.cxx (name_has_wildcard): Make static.
(dwfl_report_offline_predicate): Check & adjust behavior.
* dwflpp.h: Corresponding changes.
* tapsets.cxx: Note that kern_dw[] keys may be wildcard strings.
* testsuite/buildok/fortysix.stp: New test.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* dwflpp.cxx (dwflpp ctor): Parametrize for user/kernel modes.
Update callers.
(dwfl_report_offline_predicate): New function. Filter and
abort searches early if possible.
(setup_kernel): Use new predicate.
* dwflpp.h: Corresponding changes.
* tapsets.cxx (dwfl_report_offline_predicate): Remove this shared
implementation.
(dwarf_builder): Turn kern_dw into module_name->dwflpp* map, just
like user_dw.
(get_kern_dw): Adapt.
(dwarf_build_no_more): Adapt.
* tapsets.h: Remove old shared predicate.
* translate.cxx (dwfl_report_offline_predicate2): New function.
Filter and abort searches early if possible.
(emit_symbol_data): Use it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This will first read in the symbol table for modules, and update the
dwarf cu_function_cache with aliased names too. Then when iterating
in dwarf, all of the possible names are matched, instead of only the
canonical dwarf name.
* dwflpp.cxx (dwflpp::iterate_over_functions): call update_symtab,
and track wildcard addresses in a set to avoid alias dupes
* dwflpp.h (symbol_table::Compare): removed
* tapsets.cxx (symbol_table::map_by_addr): replaces list_by_addr
(symbol_table::sort): removed -- multimap doesn't need sorting
(symbol_table::mark_dwarf_redundancies): removed, see update_symtab
(symbol_table::purge_syscall_stubs): remove map elements inline
(dwarf_query::handle_query_module): preload the symtable.
(query_dwarf_func): don't compare the function a second time,
especially since it may have been an alias that matched at first.
(module_info::get_symtab): allow being called multiple times
(module_info::update_symtab): copy dies from the cache to the symtab,
and also add aliased names to the cache
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Mark probes rely on literal statement addresses, these are based on the
on-disk module address space. Introduce helper function to turn such
addresses into symbol addresses as expected by libdwfl. Also properly
adjust for dw bias when such addresses are used in dw queries.
* dwflpp.h (dwflpp::literal_addr_to_sym_addr): New method.
* dwflpp.cxx (query_cu_containing_address): Don't "globalize" address.
(literal_addr_to_sym_addr): New method.
* tapsets.cxx (query_module_dwarf): Turn literal addresses into symbol
addresses.
(query_dwarf_func): Likewise and adjust for dw module bias.
|
|
|
|
|
|
|
|
|
|
|
|
| |
More fat-trimming optimization for ~7% off listing syscall.*.
* dwflpp.cxx (dwflpp::iterate_over_functions): remove a parameter copy
(dwflpp::module_name_matches): Use const string& parameters
(dwflpp::name_has_wildcard): Ditto.
(dwflpp::module_name_final_match): Ditto.
(dwflpp::function_name_matches_pattern): Ditto.
(dwflpp::function_name_matches): Ditto.
(dwflpp::function_name_final_match): Ditto.
|
|
|
|
|
|
|
|
| |
Really old versions of elfutils didn't have version.h, but we still want
to support them. So add workaround also for that case.
* dwflpp.h: Define elf_getshdrstrndx as elf_getshstrndx also for really
old elfutils versions.
|
|
|
|
|
|
|
|
| |
* dwflpp.h: Check elfutils version, define elf_getshdrstrndx as
elf_getshstrndx if elfutils 0.142 detected.
* dwflpp.cxx (get_blacklist_section): Use elf_getshdrstrndx.
* tapsets.cxx (probe_table): Likewise.
(prepare_section_rejection): Likewise.
|
|
|
|
|
|
| |
It was just a basic NULL check, but creating its string temporaries was
causing a fair slowdown. Removing this function and adjusting the
callers shaves ~5% off the syscall.* elaboration time.
|
|
|
|
|
|
|
|
|
|
|
| |
This one function accounted for ~30% of my callgrind profile of
"stap -l 'syscall.*'", even though it was only called ~1200 times. We
call dwarf_getscopes for each $target variable, with the same parameters
within a given probe. Since they're no nicely grouped, it's easy to
just cache the most recent call, and the next few calls will be a hit.
Overall this cuts the number of calls down to about 300, for an easy
speed gain.
|
|
|
|
|
|
|
| |
For a call like "stap -l 'syscall.*'", I found that ~10% of the time was
spent compiling the blacklist regexps over again for each probe point.
By moving this functionality into the kernel dwflpp instance, we can
reuse the regexps and get an easy speed boost.
|
|
|
|
|
| |
This helps make it more obvious which methods are accessed by external
classes, which should help in refactoring.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
| |
The method query_cu_containing_global_address was only called by
query_cu_containing_module_address, and the latter was just doing a
simple argument transform. They are now merged into a single method,
query_cu_containing_address. The function module_address_to_global is
also merged here at its only call site.
|
|
|
|
|
|
|
|
| |
These three methods had no callers, and are thus obsolete:
dwflpp::focus_on_module_containing_global_address(Dwarf_Addr a)
dwflpp::global_address_to_module(Dwarf_Addr a)
dwflpp::cu_name_matches(string pattern)
|
|
It's not a terribly clean split, but moving it helps reveals some of the
knots that need to be untangled.
|