/** * @file op_bfd.h * Encapsulation of bfd objects * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING * * @author Philippe Elie * @author John Levon */ #ifndef OP_BFD_H #define OP_BFD_H #include "config.h" #include <vector> #include <string> #include <list> #include <map> #include <set> #include "bfd_support.h" #include "locate_images.h" #include "utility.h" #include "cached_value.h" #include "op_types.h" class op_bfd; class string_filter; class extra_images; /// all symbol vector indexing uses this type typedef size_t symbol_index_t; /** * A symbol description from a bfd point of view. This duplicate * information pointed by an asymbol, we need this duplication in case * the symbol is an artificial symbol */ class op_bfd_symbol { public: /// ctor for real symbols op_bfd_symbol(asymbol const * a); /// ctor for artificial symbols op_bfd_symbol(bfd_vma vma, size_t size, std::string const & name); bfd_vma vma() const { return symb_value + section_vma; } unsigned long value() const { return symb_value; } unsigned long filepos() const { return symb_value + section_filepos; } unsigned long symbol_endpos(void) const; asection const * section(void) const { return bfd_symbol->section; } std::string const & name() const { return symb_name; } asymbol const * symbol() const { return bfd_symbol; } size_t size() const { return symb_size; } void size(size_t s) { symb_size = s; } bool hidden() const { return symb_hidden; } bool weak() const { return symb_weak; } bool artificial() const { return symb_artificial; } /// compare two symbols by their filepos() bool operator<(op_bfd_symbol const & lhs) const; private: /// the original bfd symbol, this can be null if the symbol is an /// artificial symbol asymbol const * bfd_symbol; /// the offset of this symbol relative to the begin of the section's /// symbol unsigned long symb_value; /// the section filepos for this symbol unsigned long section_filepos; /// the section vma for this symbol bfd_vma section_vma; /// the size of this symbol size_t symb_size; /// the name of the symbol std::string symb_name; /// normally not externally visible symbol bool symb_hidden; /// whether other symbols can override it bool symb_weak; /// symbol is artificially created bool symb_artificial; /// code bytes corresponding to symbol -- used for XML generation std::string symb_bytes; }; /** * Encapsulation of a bfd object. Simplifies open/close of bfd, enumerating * symbols and retrieving informations for symbols or vma. * * Use of this class relies on a std::ostream cverb */ class op_bfd { public: /** * @param filename the name of the image file * @param symbol_filter filter to apply to symbols * @param extra_images container where all extra candidate filenames * are stored * @param ok in-out parameter: on in, if not set, don't * open the bfd (because it's not there or whatever). On out, * it's set to false if the bfd couldn't be loaded. */ op_bfd(std::string const & filename, string_filter const & symbol_filter, extra_images const & extra_images, bool & ok); /** * This constructor is used when processing an SPU profile * where the SPU ELF is embedded within the PPE binary. */ op_bfd(uint64_t spu_offset, std::string const & filename, string_filter const & symbol_filter, extra_images const & extra_images, bool & ok); std::string get_embedding_filename() const { return embedding_filename; } /// close an opened bfd image and free all related resources ~op_bfd(); /** * @param sym_idx index of the symbol * @param offset fentry number * @param filename output parameter to store filename * @param linenr output parameter to store linenr. * * Retrieve the relevant finename:linenr information for the sym_idx * at offset. If the lookup fails, return false. In some cases this * function can retrieve the filename and return true but fail to * retrieve the linenr and so can return zero in linenr */ bool get_linenr(symbol_index_t sym_idx, bfd_vma offset, std::string & filename, unsigned int & linenr) const; /** * @param sym_idx symbol index * @param start reference to start var * @param end reference to end var * * Calculates the range of sample file entries covered by sym. start * and end will be filled in appropriately. If index is the last entry * in symbol table, all entries up to the end of the sample file will * be used. After calculating start and end they are sanitized * * All errors are fatal. */ void get_symbol_range(symbol_index_t sym_idx, unsigned long long & start, unsigned long long & end) const; /** * @param start reference to the start vma * @param end reference to the end vma * * return in start, end the vma range for this binary object. */ void get_vma_range(bfd_vma & start, bfd_vma & end) const; /** return the relocated PC value for the given file offset */ bfd_vma offset_to_pc(bfd_vma offset) const; /** * If passed 0, return the file position of the .text section. * Otherwise, return the filepos of a section with a matching * vma. */ unsigned long get_start_offset(bfd_vma vma = 0) const; /** * Return the image name of the underlying binary image. For an * archive, this returns the path *within* the archive, not the * full path of the file. */ std::string get_filename() const; /// sorted vector by vma of interesting symbol. std::vector<op_bfd_symbol> syms; /// return in bits the bfd_vma size for this binary. This is needed /// because gprof output depend on the bfd_vma for *this* binary /// and do not depend on sizeof(bfd_vma) size_t bfd_arch_bits_per_address() const; /// return true if binary contain some debug information bool has_debug_info() const; /** * @param sym_idx symbol index * * Return true or false, indicating whether or not the * symbol referenced by the passed sym_idx has code available. * Some symbols have no code associated with them; for example, * artificial symbols created for anonymous memory samples or for * stripped binaries with no symbol debug info. Additionally, * if the bfd object associated with the symbol is not valid, * this function will also return false. * * NOTE: This call should be made prior to invoking * get_symbol_contents to avoid unnecessarily allocating * memory for the symbol contents. */ bool symbol_has_contents(symbol_index_t sym_idx); bool get_symbol_contents(symbol_index_t sym_index, unsigned char * contents) const; bool valid() const { return ibfd.valid(); } private: /// temporary container type for getting symbols typedef std::list<op_bfd_symbol> symbols_found_t; /** * Parse and sort in ascending order all symbols * in the file pointed to by abfd that reside in * a %SEC_CODE section. * * The symbols are filtered through * the interesting_symbol() predicate and sorted * with op_bfd_symbol::operator<() comparator. */ void get_symbols(symbols_found_t & symbols); /** * Helper function for get_symbols. * Populates bfd_syms and extracts the "interesting_symbol"s. */ void get_symbols_from_file(bfd_info & bfd, size_t start, op_bfd::symbols_found_t & symbols, bool debug_file); /** * Add the symbols in the binary, applying filtering, * and handling artificial symbols. */ void add_symbols(symbols_found_t & symbols, string_filter const & symbol_filter); /** * symbol_size - return the size of a symbol * @param sym symbol to get size * @param next next symbol in vma order if any */ size_t symbol_size(op_bfd_symbol const & sym, op_bfd_symbol const * next) const; /// create an artificial symbol for a symbolless binary op_bfd_symbol const create_artificial_symbol(); /* Generate symbols using bfd functions for * the image file associated with the ibfd arg. */ uint process_symtab(bfd_info * bfd, uint start); /// filename we open (not including archive path) std::string filename; /// path to archive std::string archive_path; /// reference to extra_images extra_images const & extra_found_images; /// file size in bytes off_t file_size; /// corresponding debug file name mutable std::string debug_filename; /// true if at least one section has (flags & SEC_DEBUGGING) != 0 mutable cached_value<bool> debug_info; /// our main bfd object: .bfd may be NULL bfd_info ibfd; // corresponding debug bfd object, if one is found mutable bfd_info dbfd; /// sections we will avoid to use symbol from, this is needed /// because elf file allows sections with identical vma and we can't /// allow overlapping symbols. Such elf layout is used actually by /// kernel modules where all code section vma are set to 0. std::vector<asection const *> filtered_section; typedef std::map<std::string, u32> filepos_map_t; // mapping of section names to filepos in the original binary filepos_map_t filepos_map; /** * If spu_offset is non-zero, embedding_filename is the file containing * the embedded SPU image. */ std::string embedding_filename; bool anon_obj; }; #endif /* !OP_BFD_H */