diff options
Diffstat (limited to 'dwflpp.h')
-rw-r--r-- | dwflpp.h | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/dwflpp.h b/dwflpp.h new file mode 100644 index 00000000..23015fdc --- /dev/null +++ b/dwflpp.h @@ -0,0 +1,383 @@ +// C++ interface to dwfl +// Copyright (C) 2005-2009 Red Hat Inc. +// Copyright (C) 2005-2007 Intel Corporation. +// Copyright (C) 2008 James.Bottomley@HansenPartnership.com +// +// This file is part of systemtap, and is free software. You can +// redistribute it and/or modify it under the terms of the GNU General +// Public License (GPL); either version 2, or (at your option) any +// later version. + +#ifndef DWFLPP_H +#define DWFLPP_H + +#include "config.h" +#include "dwarf_wrappers.h" +#include "elaborate.h" +#include "session.h" + +#include <cstring> +#include <iostream> +#include <map> +#include <set> +#include <string> +#include <vector> + +#ifdef HAVE_TR1_UNORDERED_MAP +#include <tr1/unordered_map> +#else +#include <ext/hash_map> +#endif + +extern "C" { +#include <elfutils/libdwfl.h> +} + + +struct func_info; +struct inline_instance_info; +struct symbol_table; +struct base_query; +struct dwarf_query; + +enum line_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD }; +enum info_status { info_unknown, info_present, info_absent }; + +#ifdef HAVE_TR1_UNORDERED_MAP +typedef std::tr1::unordered_map<std::string,Dwarf_Die> cu_function_cache_t; +typedef std::tr1::unordered_map<std::string,cu_function_cache_t*> mod_cu_function_cache_t; // module:cu -> function -> die +#else +struct stringhash { + // __gnu_cxx:: is needed because our own hash.h has an ambiguous hash<> decl too. + size_t operator() (const std::string& s) const + { __gnu_cxx::hash<const char*> h; return h(s.c_str()); } +}; + +typedef __gnu_cxx::hash_map<std::string,Dwarf_Die,stringhash> cu_function_cache_t; +typedef __gnu_cxx::hash_map<std::string,cu_function_cache_t*,stringhash> mod_cu_function_cache_t; // module:cu -> function -> die +#endif + +typedef std::vector<func_info> func_info_map_t; +typedef std::vector<inline_instance_info> inline_instance_map_t; + + +/* XXX FIXME functions that dwflpp needs from tapsets.cxx */ +int query_cu (Dwarf_Die * cudie, void * arg); +int query_module (Dwfl_Module *mod, void **, const char *name, + Dwarf_Addr addr, void *arg); +func_info_map_t *get_filtered_functions(dwarf_query *q); +inline_instance_map_t *get_filtered_inlines(dwarf_query *q); +void add_label_name(dwarf_query *q, const char *name); + + +struct +module_info +{ + Dwfl_Module* mod; + const char* name; + std::string elf_path; + Dwarf_Addr addr; + Dwarf_Addr bias; + symbol_table *sym_table; + info_status dwarf_status; // module has dwarf info? + info_status symtab_status; // symbol table cached? + + void get_symtab(dwarf_query *q); + + module_info(const char *name) : + mod(NULL), + name(name), + addr(0), + bias(0), + sym_table(NULL), + dwarf_status(info_unknown), + symtab_status(info_unknown) + {} + + ~module_info(); +}; + + +struct +module_cache +{ + std::map<std::string, module_info*> cache; + bool paths_collected; + bool dwarf_collected; + + module_cache() : paths_collected(false), dwarf_collected(false) {} +}; + + +struct func_info +{ + func_info() + : decl_file(NULL), decl_line(-1), addr(0), prologue_end(0), weak(false) + { + std::memset(&die, 0, sizeof(die)); + } + std::string name; + char const * decl_file; + int decl_line; + Dwarf_Die die; + Dwarf_Addr addr; + Dwarf_Addr entrypc; + 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 inline_instance_info +{ + inline_instance_info() + : decl_file(NULL), decl_line(-1) + { + std::memset(&die, 0, sizeof(die)); + } + std::string name; + char const * decl_file; + int decl_line; + Dwarf_Addr entrypc; + Dwarf_Die die; +}; + + +struct dwflpp +{ + systemtap_session & sess; + Dwfl * dwfl; + + // These are "current" values we focus on. + Dwfl_Module * module; + Dwarf * module_dwarf; + Dwarf_Addr module_bias; + module_info * mod_info; + + // These describe the current module's PC address range + Dwarf_Addr module_start; + Dwarf_Addr module_end; + + Dwarf_Die * cu; + Dwarf_Die * function; + + std::string module_name; + std::string cu_name; + std::string function_name; + + dwflpp(systemtap_session & session, const std::string& user_module=""); + ~dwflpp(); + + std::string const default_name(char const * in, char const *); + + void get_module_dwarf(bool required = false, bool report = true); + + void focus_on_module(Dwfl_Module * m, module_info * mi); + void focus_on_cu(Dwarf_Die * c); + void focus_on_function(Dwarf_Die * f); + void focus_on_module_containing_global_address(Dwarf_Addr a); + + void query_cu_containing_global_address(Dwarf_Addr a, void *arg); + void query_cu_containing_module_address(Dwarf_Addr a, void *arg); + + Dwarf_Addr module_address_to_global(Dwarf_Addr a); + Dwarf_Addr global_address_to_module(Dwarf_Addr a); + + bool module_name_matches(std::string pattern); + bool name_has_wildcard(std::string pattern); + bool module_name_final_match(std::string pattern); + + bool function_name_matches_pattern(std::string name, std::string pattern); + bool function_name_matches(std::string pattern); + bool function_name_final_match(std::string pattern); + + bool cu_name_matches(std::string pattern); + + void setup_kernel(bool debuginfo_needed = true); + void setup_user(const std::string& module_name, bool debuginfo_needed = true); + + void iterate_over_modules(int (* callback)(Dwfl_Module *, void **, + const char *, Dwarf_Addr, + void *), + base_query *data); + void query_modules(base_query *q); + + typedef std::map<Dwarf*, std::vector<Dwarf_Die>*> module_cu_cache_t; + module_cu_cache_t module_cu_cache; + + void iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg), + void * data); + + bool func_is_inline(); + + typedef std::map<std::string, std::vector<Dwarf_Die>*> cu_inl_function_cache_t; + cu_inl_function_cache_t cu_inl_function_cache; + + static int cu_inl_function_caching_callback (Dwarf_Die* func, void *arg); + + void iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg), + void * data); + + /* The global alias cache is used to resolve any DIE found in a + * module that is stubbed out with DW_AT_declaration with a defining + * DIE found in a different module. The current assumption is that + * this only applies to structures and unions, which have a global + * namespace (it deliberately only traverses program scope), so this + * cache is indexed by name. If other declaration lookups were + * added to it, it would have to be indexed by name and tag + */ + mod_cu_function_cache_t global_alias_cache; + static int global_alias_caching_callback(Dwarf_Die *die, void *arg); + + Dwarf_Die *declaration_resolve(const char *name); + + mod_cu_function_cache_t cu_function_cache; + + static int cu_function_caching_callback (Dwarf_Die* func, void *arg); + + int iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * q), + base_query * q, const std::string& function, + bool has_statement_num=false); + int iterate_over_globals (int (* callback)(Dwarf_Die *, void *), + void * data); + + bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno); + + void iterate_over_srcfile_lines (char const * srcfile, + int lines[2], + bool need_single_match, + enum line_t line_type, + void (* callback) (const dwarf_line_t& line, + void * arg), + void *data); + + void iterate_over_labels (Dwarf_Die *begin_die, + const char *sym, + const char *symfunction, + void *data, + void (* callback)(const std::string &, + const char *, + int, + Dwarf_Die *, + Dwarf_Addr, + dwarf_query *)); + + void collect_srcfiles_matching (std::string const & pattern, + std::set<char const *> & filtered_srcfiles); + + void resolve_prologue_endings (func_info_map_t & funcs); + + bool function_entrypc (Dwarf_Addr * addr); + bool die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr); + + void function_die (Dwarf_Die *d); + void function_file (char const ** c); + void function_line (int *linep); + + bool die_has_pc (Dwarf_Die & die, Dwarf_Addr pc); + + static void loc2c_error (void *, const char *fmt, ...); + + // This function generates code used for addressing computations of + // target variables. + void emit_address (struct obstack *pool, Dwarf_Addr address); + + static void loc2c_emit_address (void *arg, struct obstack *pool, + Dwarf_Addr address); + + void print_locals(Dwarf_Die *die, std::ostream &o); + + Dwarf_Attribute *find_variable_and_frame_base (Dwarf_Die *scope_die, + Dwarf_Addr pc, + std::string const & local, + const target_symbol *e, + Dwarf_Die *vardie, + Dwarf_Attribute *fb_attr_mem); + + + struct location *translate_location(struct obstack *pool, + Dwarf_Attribute *attr, + Dwarf_Addr pc, + Dwarf_Attribute *fb_attr, + struct location **tail, + const target_symbol *e); + + void print_members(Dwarf_Die *vardie, std::ostream &o); + + bool find_struct_member(const std::string& member, + Dwarf_Die *parentdie, + const target_symbol *e, + Dwarf_Die *memberdie, + std::vector<Dwarf_Attribute>& locs); + + Dwarf_Die *translate_components(struct obstack *pool, + struct location **tail, + Dwarf_Addr pc, + const target_symbol *e, + Dwarf_Die *vardie, + Dwarf_Die *die_mem, + Dwarf_Attribute *attr_mem); + + Dwarf_Die *resolve_unqualified_inner_typedie (Dwarf_Die *typedie_mem, + Dwarf_Attribute *attr_mem, + const target_symbol *e); + + void translate_final_fetch_or_store (struct obstack *pool, + struct location **tail, + Dwarf_Addr module_bias, + Dwarf_Die *die, + Dwarf_Attribute *attr_mem, + bool lvalue, + const target_symbol *e, + std::string &, + std::string &, + exp_type & ty); + + std::string express_as_string (std::string prelude, + std::string postlude, + struct location *head); + + std::string literal_stmt_for_local (Dwarf_Die *scope_die, + Dwarf_Addr pc, + std::string const & local, + const target_symbol *e, + bool lvalue, + exp_type & ty); + + + std::string literal_stmt_for_return (Dwarf_Die *scope_die, + Dwarf_Addr pc, + const target_symbol *e, + bool lvalue, + exp_type & ty); + + std::string literal_stmt_for_pointer (Dwarf_Die *type_die, + const target_symbol *e, + bool lvalue, + exp_type & ty); +}; + +#endif // DWFLPP_H + +/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ |