summaryrefslogtreecommitdiffstats
path: root/tapsets.cxx
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-06-27 21:45:37 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-06-27 21:45:37 -0400
commit53ca410a6a6032c2cde6aac6e95b57c68585e48a (patch)
tree79cda31e77dd2fee51b8f2f20e2e76989f4c8ad7 /tapsets.cxx
parent4494bb1367876f3067d0e7c90b1466b9bd88633f (diff)
parentcfa2ca3cbf2da7bbabcdf35c3085a969bd2370e4 (diff)
downloadsystemtap-steved-53ca410a6a6032c2cde6aac6e95b57c68585e48a.tar.gz
systemtap-steved-53ca410a6a6032c2cde6aac6e95b57c68585e48a.tar.xz
systemtap-steved-53ca410a6a6032c2cde6aac6e95b57c68585e48a.zip
Merge commit 'origin/master' into pr6429-comp-unwindsyms
* commit 'origin/master': Always include libdw using link groups. Fix bug in handling process(PID) probes. Added tests for 'process(PID)' variants. This commit makes changes to the VFS tapset. The changes include deprecation of syscalls2.stp: Add sys_renameat. Only probe lines once for the :* wildcard line pattern. Revert checking address in runtime bz451707: fix conversions.exp test $name Cleanup in tapsets.cxx Added powerpc support to runtime/syscall.h. Remove validating _stext due to many aliased symbols PR6646: Add checking address in runtime Fixed offset argument to vm_callback.
Diffstat (limited to 'tapsets.cxx')
-rw-r--r--tapsets.cxx175
1 files changed, 84 insertions, 91 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index a45233fc..35428fcd 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -15,6 +15,7 @@
#include "session.h"
#include "util.h"
#include "dwarf_wrappers.h"
+#include "auto_free.h"
#include <cstdlib>
#include <algorithm>
@@ -488,6 +489,27 @@ func_info
Dwarf_Addr addr;
Dwarf_Addr prologue_end;
bool weak;
+ // Comparison functor for list of functions sorted by address. The
+ // two versions that take a Dwarf_Addr let us use the STL algorithms
+ // upper_bound, equal_range et al., but we don't know whether the
+ // searched-for value will be passed as the first or the second
+ // argument.
+ struct Compare
+ {
+ bool operator() (const func_info* f1, const func_info* f2) const
+ {
+ return f1->addr < f2->addr;
+ }
+ // For doing lookups by address.
+ bool operator() (Dwarf_Addr addr, const func_info* f2) const
+ {
+ return addr < f2->addr;
+ }
+ bool operator() (const func_info* f1, Dwarf_Addr addr) const
+ {
+ return f1->addr < addr;
+ }
+ };
};
struct
@@ -566,12 +588,16 @@ symbol_table
module_info *mod_info; // associated module
map<string, func_info*> map_by_name;
vector<func_info*> list_by_addr;
+ typedef vector<func_info*>::iterator iterator_t;
+ typedef pair<iterator_t, iterator_t> range_t;
#ifdef __powerpc__
GElf_Word opd_section;
#endif
-
+ // add_symbol doesn't leave symbol table in order; call
+ // symbol_table::sort() when done adding symbols.
void add_symbol(const char *name, bool weak, Dwarf_Addr addr,
Dwarf_Addr *high_addr);
+ void sort();
enum info_status read_symbols(FILE *f, const string& path);
enum info_status read_from_elf_file(const string& path);
enum info_status read_from_text_file(const string& path);
@@ -583,7 +609,6 @@ symbol_table
func_info *lookup_symbol(const string& name);
Dwarf_Addr lookup_symbol_address(const string& name);
func_info *get_func_containing_address(Dwarf_Addr addr);
- int get_index_for_address(Dwarf_Addr addr);
symbol_table(module_info *mi) : mod_info(mi) {}
~symbol_table();
@@ -1179,16 +1204,19 @@ struct dwflpp
for (int l = lineno; ; l = l + 1)
{
+ set<int> lines_probed;
+ pair<set<int>::iterator,bool> line_probed;
dwarf_assert ("dwarf_getsrc_file",
dwarf_getsrc_file (module_dwarf,
srcfile, l, 0,
&srcsp, &nsrcs));
-
+ auto_free srcsp_af(srcsp);
if (line_type == WILDCARD || line_type == RANGE)
{
Dwarf_Addr line_addr;
dwarf_lineno (srcsp [0], &lineno);
- if (lineno != l)
+ line_probed = lines_probed.insert(lineno);
+ if (lineno != l || line_probed.second == false)
continue;
dwarf_lineaddr (srcsp [0], &line_addr);
if (dwarf_haspc (function, line_addr) != 1)
@@ -1247,24 +1275,15 @@ struct dwflpp
throw semantic_error (advice.str());
}
- try
- {
- for (size_t i = 0; i < nsrcs; ++i)
- {
- if (pending_interrupts) return;
- if (srcsp [i]) // skip over mismatched lines
- callback (dwarf_line_t(srcsp[i]), data);
- }
- }
- catch (...)
- {
- free (srcsp);
- throw;
- }
- if (line_type != WILDCARD || l == lines[1])
- break;
+ for (size_t i = 0; i < nsrcs; ++i)
+ {
+ if (pending_interrupts) return;
+ if (srcsp [i]) // skip over mismatched lines
+ callback (dwarf_line_t(srcsp[i]), data);
+ }
+ if (line_type != WILDCARD || l == lines[1])
+ break;
}
- free (srcsp);
}
@@ -2695,12 +2714,12 @@ dwarf_query::query_module_symtab()
<< endl;
return;
}
-
- size_t i;
- size_t nsyms = sym_table->list_by_addr.size();
- for (i = 0; i < nsyms; i++)
+ symbol_table::iterator_t iter;
+ for (iter = sym_table->list_by_addr.begin();
+ iter != sym_table->list_by_addr.end();
+ ++iter)
{
- fi = sym_table->list_by_addr.at(i);
+ fi = *iter;
if (!null_die(&fi->die))
continue; // already handled in query_module_dwarf()
if (dw.function_name_matches_pattern(fi->name, function_str_val))
@@ -4742,14 +4761,8 @@ dwarf_builder::build(systemtap_session & sess,
symbol_table::~symbol_table()
{
- // map::clear() and vector::clear() don't call destructors for
- // pointers, only for objects.
- int i;
- int nsym = (int) list_by_addr.size();
- for (i = 0; i < nsym; i++)
- delete list_by_addr.at(i);
- list_by_addr.clear();
- map_by_name.clear();
+ for (iterator_t i = list_by_addr.begin(); i != list_by_addr.end(); ++i)
+ delete *i;
}
void
@@ -4768,18 +4781,7 @@ symbol_table::add_symbol(const char *name, bool weak, Dwarf_Addr addr,
map_by_name[fi->name] = fi;
// TODO: Use a multimap in case there are multiple static
// functions with the same name?
- if (addr >= *high_addr)
- {
- list_by_addr.push_back(fi);
- *high_addr = addr;
- }
- else
- {
- // Symbols aren't in numerical order. FWIW, sort(1) doesn't
- // handle hex numbers without the leading 0x.
- int index = get_index_for_address(fi->addr);
- list_by_addr.insert(list_by_addr.begin()+(index+1), fi);
- }
+ list_by_addr.push_back(fi);
}
enum info_status
@@ -4787,7 +4789,8 @@ symbol_table::read_symbols(FILE *f, const string& path)
{
// Based on do_kernel_symbols() in runtime/staprun/symbols.c
int ret;
- char *name, *mod;
+ char *name = 0;
+ char *mod = 0;
char type;
unsigned long long addr;
Dwarf_Addr high_addr = 0;
@@ -4796,6 +4799,8 @@ symbol_table::read_symbols(FILE *f, const string& path)
// %as (non-POSIX) mallocs space for the string and stores its address.
while ((ret = fscanf(f, "%llx %c %as [%as", &addr, &type, &name, &mod)) > 0)
{
+ auto_free free_name(name);
+ auto_free free_mod(mod);
line++;
if (ret < 3)
{
@@ -4807,26 +4812,23 @@ symbol_table::read_symbols(FILE *f, const string& path)
// Caller should delete symbol_table object.
return info_absent;
}
- if (ret > 3)
+ else if (ret > 3)
{
// Modules are loaded above the kernel, so if we're getting
// modules, we're done.
- free(name);
- free(mod);
- goto done;
+ break;
}
if (type == 'T' || type == 't' || type == 'W')
add_symbol(name, (type == 'W'), (Dwarf_Addr) addr, &high_addr);
- free(name);
}
-done:
if (list_by_addr.size() < 1)
{
cerr << "Symbol table error: "
<< path << " contains no function symbols." << endl;
return info_absent;
}
+ sort();
return info_present;
}
@@ -4938,6 +4940,7 @@ symbol_table::get_from_elf()
add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK),
sym.st_value, &high_addr);
}
+ sort();
return info_present;
}
@@ -4979,35 +4982,12 @@ symbol_table::mark_dwarf_redundancies(dwflpp *dw)
func_info *
symbol_table::get_func_containing_address(Dwarf_Addr addr)
{
- int index = get_index_for_address(addr);
- if (index < 0)
+ iterator_t iter = upper_bound(list_by_addr.begin(), list_by_addr.end(), addr,
+ func_info::Compare());
+ if (iter == list_by_addr.begin())
return NULL;
- return list_by_addr.at(index);
-}
-
-// Find the index in list_by_addr of the last element whose address
-// is <= addr. Returns -1 if addr is less than the first address in
-// list_by_addr.
-int
-symbol_table::get_index_for_address(Dwarf_Addr addr)
-{
- // binary search from runtime/sym.c
- int begin = 0;
- int mid;
- int end = list_by_addr.size();
-
- if (end == 0 || addr < list_by_addr.at(0)->addr)
- return -1;
- do
- {
- mid = (begin + end) / 2;
- if (addr < list_by_addr.at(mid)->addr)
- end = mid;
- else
- begin = mid;
- }
- while (begin + 1 < end);
- return begin;
+ else
+ return *(iter - 1);
}
func_info *
@@ -5042,17 +5022,30 @@ symbol_table::purge_syscall_stubs()
Dwarf_Addr stub_addr = lookup_symbol_address("sys_ni_syscall");
if (stub_addr == 0)
return;
- for (size_t i = 0; i < list_by_addr.size(); i++)
- {
- func_info *fi = list_by_addr.at(i);
- if (fi->weak && fi->addr == stub_addr && fi->name != "sys_ni_syscall")
+ range_t purge_range = equal_range(list_by_addr.begin(), list_by_addr.end(),
+ stub_addr, func_info::Compare());
+ for (iterator_t iter = purge_range.first;
+ iter != purge_range.second;
+ ++iter)
+ {
+ func_info *fi = *iter;
+ if (fi->weak && fi->name != "sys_ni_syscall")
{
- list_by_addr.erase(list_by_addr.begin()+i);
- map_by_name.erase(fi->name);
- delete fi;
- i--;
- }
+ map_by_name.erase(fi->name);
+ delete fi;
+ *iter = 0;
+ }
}
+ // Range might have null pointer entries that should be erased.
+ list_by_addr.erase(remove(purge_range.first, purge_range.second,
+ (func_info*)0),
+ purge_range.second);
+}
+
+void
+symbol_table::sort()
+{
+ stable_sort(list_by_addr.begin(), list_by_addr.end(), func_info::Compare());
}
void
@@ -5823,7 +5816,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
// Emit a "fake" probe decl that is really a hook for to get
// our vm_callback called.
s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA";
- emit_vm_callback_probe_decl (s, false, NULL, it->first,
+ emit_vm_callback_probe_decl (s, false, "", it->first,
"__stp_tf_vm_cb");
s.op->newline() << "#endif";