00001 /** 00002 * @file op_bfd.h 00003 * Encapsulation of bfd objects 00004 * 00005 * @remark Copyright 2002 OProfile authors 00006 * @remark Read the file COPYING 00007 * 00008 * @author Philippe Elie 00009 * @author John Levon 00010 */ 00011 00012 #ifndef OP_BFD_H 00013 #define OP_BFD_H 00014 00015 #include "config.h" 00016 00017 #include <vector> 00018 #include <string> 00019 #include <list> 00020 #include <map> 00021 #include <set> 00022 00023 #include "bfd_support.h" 00024 #include "locate_images.h" 00025 #include "utility.h" 00026 #include "cached_value.h" 00027 #include "op_types.h" 00028 00029 class op_bfd; 00030 class string_filter; 00031 class extra_images; 00032 00033 /// all symbol vector indexing uses this type 00034 typedef size_t symbol_index_t; 00035 00036 /** 00037 * A symbol description from a bfd point of view. This duplicate 00038 * information pointed by an asymbol, we need this duplication in case 00039 * the symbol is an artificial symbol 00040 */ 00041 class op_bfd_symbol { 00042 public: 00043 00044 /// ctor for real symbols 00045 op_bfd_symbol(asymbol const * a); 00046 00047 /// ctor for artificial symbols 00048 op_bfd_symbol(bfd_vma vma, size_t size, std::string const & name); 00049 00050 bfd_vma vma() const { return symb_value + section_vma; } 00051 unsigned long value() const { return symb_value; } 00052 unsigned long filepos() const { return symb_value + section_filepos; } 00053 unsigned long symbol_endpos(void) const; 00054 asection const * section(void) const { return bfd_symbol->section; } 00055 std::string const & name() const { return symb_name; } 00056 asymbol const * symbol() const { return bfd_symbol; } 00057 size_t size() const { return symb_size; } 00058 void size(size_t s) { symb_size = s; } 00059 bool hidden() const { return symb_hidden; } 00060 bool weak() const { return symb_weak; } 00061 bool artificial() const { return symb_artificial; } 00062 00063 /// compare two symbols by their filepos() 00064 bool operator<(op_bfd_symbol const & lhs) const; 00065 00066 private: 00067 /// the original bfd symbol, this can be null if the symbol is an 00068 /// artificial symbol 00069 asymbol const * bfd_symbol; 00070 /// the offset of this symbol relative to the begin of the section's 00071 /// symbol 00072 unsigned long symb_value; 00073 /// the section filepos for this symbol 00074 unsigned long section_filepos; 00075 /// the section vma for this symbol 00076 bfd_vma section_vma; 00077 /// the size of this symbol 00078 size_t symb_size; 00079 /// the name of the symbol 00080 std::string symb_name; 00081 /// normally not externally visible symbol 00082 bool symb_hidden; 00083 /// whether other symbols can override it 00084 bool symb_weak; 00085 /// symbol is artificially created 00086 bool symb_artificial; 00087 /// code bytes corresponding to symbol -- used for XML generation 00088 std::string symb_bytes; 00089 }; 00090 00091 /** 00092 * Encapsulation of a bfd object. Simplifies open/close of bfd, enumerating 00093 * symbols and retrieving informations for symbols or vma. 00094 * 00095 * Use of this class relies on a std::ostream cverb 00096 */ 00097 class op_bfd { 00098 public: 00099 /** 00100 * @param filename the name of the image file 00101 * @param symbol_filter filter to apply to symbols 00102 * @param extra_images container where all extra candidate filenames 00103 * are stored 00104 * @param ok in-out parameter: on in, if not set, don't 00105 * open the bfd (because it's not there or whatever). On out, 00106 * it's set to false if the bfd couldn't be loaded. 00107 */ 00108 op_bfd(std::string const & filename, 00109 string_filter const & symbol_filter, 00110 extra_images const & extra_images, 00111 bool & ok); 00112 00113 /** 00114 * This constructor is used when processing an SPU profile 00115 * where the SPU ELF is embedded within the PPE binary. 00116 */ 00117 op_bfd(uint64_t spu_offset, 00118 std::string const & filename, 00119 string_filter const & symbol_filter, 00120 extra_images const & extra_images, 00121 bool & ok); 00122 00123 std::string get_embedding_filename() const { return embedding_filename; } 00124 00125 /// close an opened bfd image and free all related resources 00126 ~op_bfd(); 00127 00128 /** 00129 * @param sym_idx index of the symbol 00130 * @param offset fentry number 00131 * @param filename output parameter to store filename 00132 * @param linenr output parameter to store linenr. 00133 * 00134 * Retrieve the relevant finename:linenr information for the sym_idx 00135 * at offset. If the lookup fails, return false. In some cases this 00136 * function can retrieve the filename and return true but fail to 00137 * retrieve the linenr and so can return zero in linenr 00138 */ 00139 bool get_linenr(symbol_index_t sym_idx, bfd_vma offset, 00140 std::string & filename, unsigned int & linenr) const; 00141 00142 /** 00143 * @param sym_idx symbol index 00144 * @param start reference to start var 00145 * @param end reference to end var 00146 * 00147 * Calculates the range of sample file entries covered by sym. start 00148 * and end will be filled in appropriately. If index is the last entry 00149 * in symbol table, all entries up to the end of the sample file will 00150 * be used. After calculating start and end they are sanitized 00151 * 00152 * All errors are fatal. 00153 */ 00154 void get_symbol_range(symbol_index_t sym_idx, 00155 unsigned long long & start, unsigned long long & end) const; 00156 00157 /** 00158 * @param start reference to the start vma 00159 * @param end reference to the end vma 00160 * 00161 * return in start, end the vma range for this binary object. 00162 */ 00163 void get_vma_range(bfd_vma & start, bfd_vma & end) const; 00164 00165 /** return the relocated PC value for the given file offset */ 00166 bfd_vma offset_to_pc(bfd_vma offset) const; 00167 00168 /** 00169 * If passed 0, return the file position of the .text section. 00170 * Otherwise, return the filepos of a section with a matching 00171 * vma. 00172 */ 00173 unsigned long get_start_offset(bfd_vma vma = 0) const; 00174 00175 /** 00176 * Return the image name of the underlying binary image. For an 00177 * archive, this returns the path *within* the archive, not the 00178 * full path of the file. 00179 */ 00180 std::string get_filename() const; 00181 00182 /// sorted vector by vma of interesting symbol. 00183 std::vector<op_bfd_symbol> syms; 00184 00185 /// return in bits the bfd_vma size for this binary. This is needed 00186 /// because gprof output depend on the bfd_vma for *this* binary 00187 /// and do not depend on sizeof(bfd_vma) 00188 size_t bfd_arch_bits_per_address() const; 00189 00190 /// return true if binary contain some debug information 00191 bool has_debug_info() const; 00192 00193 /** 00194 * @param sym_idx symbol index 00195 * 00196 * Return true or false, indicating whether or not the 00197 * symbol referenced by the passed sym_idx has code available. 00198 * Some symbols have no code associated with them; for example, 00199 * artificial symbols created for anonymous memory samples or for 00200 * stripped binaries with no symbol debug info. Additionally, 00201 * if the bfd object associated with the symbol is not valid, 00202 * this function will also return false. 00203 * 00204 * NOTE: This call should be made prior to invoking 00205 * get_symbol_contents to avoid unnecessarily allocating 00206 * memory for the symbol contents. 00207 */ 00208 bool symbol_has_contents(symbol_index_t sym_idx); 00209 00210 bool get_symbol_contents(symbol_index_t sym_index, 00211 unsigned char * contents) const; 00212 00213 bool valid() const { return ibfd.valid(); } 00214 00215 bfd_vma get_vma_adj(void) const { return vma_adj; } 00216 00217 private: 00218 /// temporary container type for getting symbols 00219 typedef std::list<op_bfd_symbol> symbols_found_t; 00220 00221 /** 00222 * Parse and sort in ascending order all symbols 00223 * in the file pointed to by abfd that reside in 00224 * a %SEC_CODE section. 00225 * 00226 * The symbols are filtered through 00227 * the interesting_symbol() predicate and sorted 00228 * with op_bfd_symbol::operator<() comparator. 00229 */ 00230 void get_symbols(symbols_found_t & symbols); 00231 00232 /** 00233 * Helper function for get_symbols. 00234 * Populates bfd_syms and extracts the "interesting_symbol"s. 00235 */ 00236 void get_symbols_from_file(bfd_info & bfd, size_t start, 00237 op_bfd::symbols_found_t & symbols, 00238 bool debug_file); 00239 00240 /** 00241 * Add the symbols in the binary, applying filtering, 00242 * and handling artificial symbols. 00243 */ 00244 void add_symbols(symbols_found_t & symbols, 00245 string_filter const & symbol_filter); 00246 00247 /** 00248 * symbol_size - return the size of a symbol 00249 * @param sym symbol to get size 00250 * @param next next symbol in vma order if any 00251 */ 00252 size_t symbol_size(op_bfd_symbol const & sym, 00253 op_bfd_symbol const * next) const; 00254 00255 /// create an artificial symbol for a symbolless binary 00256 op_bfd_symbol const create_artificial_symbol(); 00257 00258 /* Generate symbols using bfd functions for 00259 * the image file associated with the ibfd arg. 00260 */ 00261 uint process_symtab(bfd_info * bfd, uint start); 00262 00263 /// filename we open (not including archive path) 00264 std::string filename; 00265 00266 /// path to archive 00267 std::string archive_path; 00268 00269 /// reference to extra_images 00270 extra_images const & extra_found_images; 00271 00272 /// file size in bytes 00273 off_t file_size; 00274 00275 /// corresponding debug file name 00276 mutable std::string debug_filename; 00277 00278 /// true if at least one section has (flags & SEC_DEBUGGING) != 0 00279 mutable cached_value<bool> debug_info; 00280 00281 /// our main bfd object: .bfd may be NULL 00282 bfd_info ibfd; 00283 00284 // corresponding debug bfd object, if one is found 00285 mutable bfd_info dbfd; 00286 00287 /// sections we will avoid to use symbol from, this is needed 00288 /// because elf file allows sections with identical vma and we can't 00289 /// allow overlapping symbols. Such elf layout is used actually by 00290 /// kernel modules where all code section vma are set to 0. 00291 std::vector<asection const *> filtered_section; 00292 00293 typedef std::map<std::string, u32> filepos_map_t; 00294 // mapping of section names to filepos in the original binary 00295 filepos_map_t filepos_map; 00296 00297 /** 00298 * If spu_offset is non-zero, embedding_filename is the file containing 00299 * the embedded SPU image. 00300 */ 00301 std::string embedding_filename; 00302 00303 bool anon_obj; 00304 00305 /** 00306 * If a runtime binary is prelinked, then its p_vaddr field in the 00307 * first PT_LOAD segment will give the address where the binary will 00308 * be loaded into memory. However, the corresponding debuginfo file 00309 * may have a different p_vaddr value. In profile_container::add_samples, 00310 * this difference is handled by adding the "base_vma" to the sample 00311 * vma. However, if the runtime binary has no symbol information at all, 00312 * then the "base_vma" is obtained from the debuginfo symbol information. 00313 * For opreport, this works OK, since under such conditions, ALL symbol 00314 * and debug data is then obtained from the debuginfo files, and the sample 00315 * vma's should match up fine with the symbol vma's in the debuginfo file. 00316 * But when doing 'opannoate --assembly', the real (runtime) image is used for 00317 * annotation, and, thus, we may have a mis-match between real image p_vaddr 00318 * and the impliled p_vaddr stored with the samples. To handle this case, 00319 * we do the following: When a bfd_info is created for a debuginfo 00320 * file, we set vma_adj to the difference between runtime load address 00321 * and the p_vaddr of the first PT_LOAD segment of the debuginfo file, if and 00322 * only if the real image has no symbol info; otherwise vma_adj is set to 0. 00323 */ 00324 bfd_vma vma_adj; 00325 00326 }; 00327 00328 00329 #endif /* !OP_BFD_H */
1.6.1