Home | History | Annotate | Download | only in libutil++
      1 /**
      2  * @file op_bfd.h
      3  * Encapsulation of bfd objects
      4  *
      5  * @remark Copyright 2002 OProfile authors
      6  * @remark Read the file COPYING
      7  *
      8  * @author Philippe Elie
      9  * @author John Levon
     10  */
     11 
     12 #ifndef OP_BFD_H
     13 #define OP_BFD_H
     14 
     15 #include "config.h"
     16 
     17 #include <vector>
     18 #include <string>
     19 #include <list>
     20 #include <map>
     21 #include <set>
     22 
     23 #include "bfd_support.h"
     24 #include "locate_images.h"
     25 #include "utility.h"
     26 #include "cached_value.h"
     27 #include "op_types.h"
     28 
     29 class op_bfd;
     30 class string_filter;
     31 class extra_images;
     32 
     33 /// all symbol vector indexing uses this type
     34 typedef size_t symbol_index_t;
     35 
     36 /**
     37  * A symbol description from a bfd point of view. This duplicate
     38  * information pointed by an asymbol, we need this duplication in case
     39  * the symbol is an artificial symbol
     40  */
     41 class op_bfd_symbol {
     42 public:
     43 
     44 	/// ctor for real symbols
     45 	op_bfd_symbol(asymbol const * a);
     46 
     47 	/// ctor for artificial symbols
     48 	op_bfd_symbol(bfd_vma vma, size_t size, std::string const & name);
     49 
     50 	bfd_vma vma() const { return symb_value + section_vma; }
     51 	unsigned long value() const { return symb_value; }
     52 	unsigned long filepos() const { return symb_value + section_filepos; }
     53 	unsigned long symbol_endpos(void) const;
     54 	asection const * section(void) const { return bfd_symbol->section; }
     55 	std::string const & name() const { return symb_name; }
     56 	asymbol const * symbol() const { return bfd_symbol; }
     57 	size_t size() const { return symb_size; }
     58 	void size(size_t s) { symb_size = s; }
     59 	bool hidden() const { return symb_hidden; }
     60 	bool weak() const { return symb_weak; }
     61 	bool artificial() const { return symb_artificial; }
     62 
     63 	/// compare two symbols by their filepos()
     64 	bool operator<(op_bfd_symbol const & lhs) const;
     65 
     66 private:
     67 	/// the original bfd symbol, this can be null if the symbol is an
     68 	/// artificial symbol
     69 	asymbol const * bfd_symbol;
     70 	/// the offset of this symbol relative to the begin of the section's
     71 	/// symbol
     72 	unsigned long symb_value;
     73 	/// the section filepos for this symbol
     74 	unsigned long section_filepos;
     75 	/// the section vma for this symbol
     76 	bfd_vma section_vma;
     77 	/// the size of this symbol
     78 	size_t symb_size;
     79 	/// the name of the symbol
     80 	std::string symb_name;
     81 	/// normally not externally visible symbol
     82 	bool symb_hidden;
     83 	/// whether other symbols can override it
     84 	bool symb_weak;
     85 	/// symbol is artificially created
     86 	bool symb_artificial;
     87 	/// code bytes corresponding to symbol -- used for XML generation
     88 	std::string symb_bytes;
     89 };
     90 
     91 /**
     92  * Encapsulation of a bfd object. Simplifies open/close of bfd, enumerating
     93  * symbols and retrieving informations for symbols or vma.
     94  *
     95  * Use of this class relies on a std::ostream cverb
     96  */
     97 class op_bfd {
     98 public:
     99 	/**
    100 	 * @param filename  the name of the image file
    101 	 * @param symbol_filter  filter to apply to symbols
    102 	 * @param extra_images container where all extra candidate filenames
    103 	 *    are stored
    104 	 * @param ok in-out parameter: on in, if not set, don't
    105 	 * open the bfd (because it's not there or whatever). On out,
    106 	 * it's set to false if the bfd couldn't be loaded.
    107 	 */
    108 	op_bfd(std::string const & filename,
    109 	       string_filter const & symbol_filter,
    110 	       extra_images const & extra_images,
    111 	       bool & ok);
    112 
    113 	/**
    114 	 * This constructor is used when processing an SPU profile
    115 	 * where the SPU ELF is embedded within the PPE binary.
    116 	 */
    117 	op_bfd(uint64_t spu_offset,
    118 	       std::string const & filename,
    119 	       string_filter const & symbol_filter,
    120 	       extra_images const & extra_images,
    121 	       bool & ok);
    122 
    123 	std::string get_embedding_filename() const { return embedding_filename; }
    124 
    125 	/// close an opened bfd image and free all related resources
    126 	~op_bfd();
    127 
    128 	/**
    129 	 * @param sym_idx index of the symbol
    130 	 * @param offset fentry number
    131 	 * @param filename output parameter to store filename
    132 	 * @param linenr output parameter to store linenr.
    133 	 *
    134 	 * Retrieve the relevant finename:linenr information for the sym_idx
    135 	 * at offset. If the lookup fails, return false. In some cases this
    136 	 * function can retrieve the filename and return true but fail to
    137 	 * retrieve the linenr and so can return zero in linenr
    138 	 */
    139 	bool get_linenr(symbol_index_t sym_idx, bfd_vma offset,
    140 			std::string & filename, unsigned int & linenr) const;
    141 
    142 	/**
    143 	 * @param sym_idx symbol index
    144 	 * @param start reference to start var
    145 	 * @param end reference to end var
    146 	 *
    147 	 * Calculates the range of sample file entries covered by sym. start
    148 	 * and end will be filled in appropriately. If index is the last entry
    149 	 * in symbol table, all entries up to the end of the sample file will
    150 	 * be used.  After calculating start and end they are sanitized
    151 	 *
    152 	 * All errors are fatal.
    153 	 */
    154 	void get_symbol_range(symbol_index_t sym_idx,
    155 			      unsigned long long & start, unsigned long long & end) const;
    156 
    157 	/**
    158 	 * @param start reference to the start vma
    159 	 * @param end reference to the end vma
    160 	 *
    161 	 * return in start, end the vma range for this binary object.
    162 	 */
    163 	void get_vma_range(bfd_vma & start, bfd_vma & end) const;
    164 
    165 	/** return the relocated PC value for the given file offset */
    166 	bfd_vma offset_to_pc(bfd_vma offset) const;
    167 
    168 	/**
    169 	 * If passed 0, return the file position of the .text section.
    170 	 * Otherwise, return the filepos of a section with a matching
    171 	 * vma.
    172 	 */
    173 	unsigned long get_start_offset(bfd_vma vma = 0) const;
    174 
    175 	/**
    176 	 * Return the image name of the underlying binary image. For an
    177 	 * archive, this returns the path *within* the archive, not the
    178 	 * full path of the file.
    179 	 */
    180 	std::string get_filename() const;
    181 
    182 	/// sorted vector by vma of interesting symbol.
    183 	std::vector<op_bfd_symbol> syms;
    184 
    185 	/// return in bits the bfd_vma size for this binary. This is needed
    186 	/// because gprof output depend on the bfd_vma for *this* binary
    187 	/// and do not depend on sizeof(bfd_vma)
    188 	size_t bfd_arch_bits_per_address() const;
    189 
    190 	/// return true if binary contain some debug information
    191 	bool has_debug_info() const;
    192 
    193 	/**
    194 	 * @param sym_idx symbol index
    195 	 *
    196 	 * Return true or false, indicating whether or not the
    197 	 * symbol referenced by the passed sym_idx has code available.
    198 	 * Some symbols have no code associated with them; for example,
    199 	 * artificial symbols created for anonymous memory samples or for
    200 	 * stripped binaries with no symbol debug info.  Additionally,
    201 	 * if the bfd object associated with the symbol is not valid,
    202 	 * this function will also return false.
    203 	 *
    204 	 * NOTE:  This call should be made prior to invoking
    205 	 *        get_symbol_contents to avoid unnecessarily allocating
    206 	 *        memory for the symbol contents.
    207 	 */
    208 	bool symbol_has_contents(symbol_index_t sym_idx);
    209 
    210 	bool get_symbol_contents(symbol_index_t sym_index,
    211 		unsigned char * contents) const;
    212 
    213 	bool valid() const { return ibfd.valid(); }
    214 
    215 private:
    216 	/// temporary container type for getting symbols
    217 	typedef std::list<op_bfd_symbol> symbols_found_t;
    218 
    219 	/**
    220 	 * Parse and sort in ascending order all symbols
    221 	 * in the file pointed to by abfd that reside in
    222 	 * a %SEC_CODE section.
    223 	 *
    224 	 * The symbols are filtered through
    225 	 * the interesting_symbol() predicate and sorted
    226 	 * with op_bfd_symbol::operator<() comparator.
    227 	 */
    228 	void get_symbols(symbols_found_t & symbols);
    229 
    230 	/**
    231 	 * Helper function for get_symbols.
    232 	 * Populates bfd_syms and extracts the "interesting_symbol"s.
    233 	 */
    234 	void get_symbols_from_file(bfd_info & bfd, size_t start,
    235 				   op_bfd::symbols_found_t & symbols,
    236 				   bool debug_file);
    237 
    238 	/**
    239 	 * Add the symbols in the binary, applying filtering,
    240 	 * and handling artificial symbols.
    241 	 */
    242 	void add_symbols(symbols_found_t & symbols,
    243 	                 string_filter const & symbol_filter);
    244 
    245 	/**
    246 	 * symbol_size - return the size of a symbol
    247 	 * @param sym  symbol to get size
    248 	 * @param next  next symbol in vma order if any
    249 	 */
    250 	size_t symbol_size(op_bfd_symbol const & sym,
    251 			   op_bfd_symbol const * next) const;
    252 
    253 	/// create an artificial symbol for a symbolless binary
    254 	op_bfd_symbol const create_artificial_symbol();
    255 
    256         /* Generate symbols using bfd functions for
    257 	 * the image file associated with the ibfd arg.
    258 	 */
    259 	uint process_symtab(bfd_info * bfd, uint start);
    260 
    261 	/// filename we open (not including archive path)
    262 	std::string filename;
    263 
    264 	/// path to archive
    265 	std::string archive_path;
    266 
    267 	/// reference to extra_images
    268 	extra_images const & extra_found_images;
    269 
    270 	/// file size in bytes
    271 	off_t file_size;
    272 
    273 	/// corresponding debug file name
    274 	mutable std::string debug_filename;
    275 
    276 	/// true if at least one section has (flags & SEC_DEBUGGING) != 0
    277 	mutable cached_value<bool> debug_info;
    278 
    279 	/// our main bfd object: .bfd may be NULL
    280 	bfd_info ibfd;
    281 
    282 	// corresponding debug bfd object, if one is found
    283 	mutable bfd_info dbfd;
    284 
    285 	/// sections we will avoid to use symbol from, this is needed
    286 	/// because elf file allows sections with identical vma and we can't
    287 	/// allow overlapping symbols. Such elf layout is used actually by
    288 	/// kernel modules where all code section vma are set to 0.
    289 	std::vector<asection const *> filtered_section;
    290 
    291 	typedef std::map<std::string, u32> filepos_map_t;
    292 	// mapping of section names to filepos in the original binary
    293 	filepos_map_t filepos_map;
    294 
    295 	/**
    296 	 * If spu_offset is non-zero, embedding_filename is the file containing
    297 	 * the embedded SPU image.
    298 	 */
    299 	std::string embedding_filename;
    300 
    301 	bool anon_obj;
    302 };
    303 
    304 
    305 #endif /* !OP_BFD_H */
    306