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
29class op_bfd;
30class string_filter;
31class extra_images;
32
33/// all symbol vector indexing uses this type
34typedef 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 */
41class op_bfd_symbol {
42public:
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
66private:
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 */
97class op_bfd {
98public:
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
215private:
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