1/* Copyright (C) 2007-2010 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12
13/*
14 * Contains declaration of ElfFile classes that encapsulate an ELF file.
15 */
16
17#ifndef ELFF_ELF_FILE_H_
18#define ELFF_ELF_FILE_H_
19
20#include "dwarf_die.h"
21#include "elf_mapped_section.h"
22#include "elff_api.h"
23#include "android/utils/mapfile.h"
24
25/* Encapsulates architecture-independent functionality of an ELF file.
26 *
27 * This class is a base class for templated ElfFileImpl. This class implements
28 * functionality around an ELF file that is independent from particulars of the
29 * ELF's CPU architectire, while ElfFileImpl handles all particulars of CPU
30 * architecture (namely, 32 or 64-bit), for which ELF file has been built.
31 *
32 * NOTE: This class operates on ELF sections that have been mapped to memory.
33 *
34 */
35class ElfFile {
36 public:
37  /* Constructs ElfFile instance. */
38  ElfFile();
39
40  /* Destructs ElfFile instance. */
41  virtual ~ElfFile();
42
43  /* Creates ElfFileImpl instance, depending on ELF file CPU architecture.
44   * This method will collect initial information about requested ELF file,
45   * and will instantiate appropriate ElfFileImpl class object for it.
46   * Param:
47   *  path - Full path to the ELF file.
48   * Return:
49   *  Initialized ElfFileImpl instance, typecasted back to ElfFile object on
50   *  success, or NULL on failure, with errno providing extended error
51   *  information.
52   */
53  static ElfFile* Create(const char* path);
54
55  /* Checks if ELF file is a 64, or 32-bit ELF file. */
56  bool is_ELF_64() const {
57    return is_ELF_64_;
58  }
59  bool is_ELF_32() const {
60    return !is_ELF_64_;
61  }
62
63  /* Checks if ELF file data format is big, or little-endian. */
64  bool is_elf_big_endian() const {
65    return is_elf_big_endian_;
66  }
67  bool is_elf_little_endian() const {
68    return !is_elf_big_endian_;
69  }
70
71  /* Checks whether or not endianness of CPU this library is built for matches
72   * endianness of the ELF file that is represented with this instance. */
73  bool same_endianness() const {
74    return same_endianness_;
75  }
76
77  /* Checks if format of DWARF data in this file is 64, or 32-bit. */
78  bool is_DWARF_64() const {
79    return is_DWARF_64_;
80  }
81  bool is_DWARF_32() const {
82    return !is_DWARF_64_;
83  }
84
85  /* Gets DWARF objects allocator for this instance. */
86  class ElfAllocator* allocator() const {
87    return allocator_;
88  }
89
90  /* Gets head of compilation unit list, collected during parsing of this file.
91   * NOTE: list of collected compilation units returned from this method is
92   * in reverse order relatively to the order CUs have been added to the list
93   * during ELF file parsing.
94   */
95  class DwarfCU* last_cu() const {
96    return last_cu_;
97  }
98
99  /* Gets number of compilation units, collected during parsing of
100   * this ELF file with parse_compilation_units() method.
101   */
102  int cu_count() const {
103    return cu_count_;
104  }
105
106  /* Gets  executable file flag */
107  bool is_exec() const {
108      return is_exec_;
109  }
110
111 protected:
112  /* Initializes ElfFile instance. This method is called from Create method of
113   * this class after appropriate ElfFileImpl instance has been created. Note,
114   * that Create() method will validate that requested file is an ELF file,
115   * prior to instantiating of an ElfFileImpl object, and calling this method.
116   * Param:
117   *  elf_hdr - Address of the common ELF file header.
118   *  path - See Create().
119   * Return:
120   *  true on success, or false on failure, with errno containing extended
121   *  error information.
122   */
123  virtual bool initialize(const Elf_CommonHdr* elf_hdr, const char* path);
124
125/*=============================================================================
126 * Endianness helper methods.
127 * Since endianness of ELF file may differ from the endianness of the CPU this
128 * library runs on, every time a value is required from a section of the ELF
129 * file, it must be first pulled out of that section to a local variable, and
130 * then used from that local variable. While value is pulled from ELF file
131 * section, it must be converted accordingly to the endianness of the CPU and
132 * ELF file. Routines bellow provide such functionality.
133=============================================================================*/
134
135 public:
136  /* Pulls one byte value from ELF file. Note that for one byte we don't need
137   * to do any endianness conversion, and these two methods are provided purely
138   * for completness of the API.
139   * Param:
140   *  val - References value inside ELF file buffer to pull data from.
141   * Return
142   *  Pulled value with endianness appropriate for the CPU this library is
143   *  running on.
144   */
145  uint8_t pull_val(const uint8_t* val) const {
146    return *val;
147  }
148  uint8_t pull_val(const uint8_t& val) const {
149    return val;
150  }
151  int8_t pull_val(const int8_t* val) const {
152    return *val;
153  }
154  int8_t pull_val(const int8_t& val) const {
155    return val;
156  }
157
158  /* Pulls two byte value from ELF file.
159   * Param:
160   *  val - References value inside ELF file buffer to pull data from.
161   * Return
162   *  Pulled value with endianness appropriate for the CPU this library is
163   *  running on.
164   */
165  uint16_t pull_val(const uint16_t* val) const {
166    if (same_endianness()) {
167      return *val;
168    }
169    if (is_elf_big_endian()) {
170      return (uint16_t)get_byte(val, 0) << 8 | get_byte(val, 1);
171    } else {
172      return (uint16_t)get_byte(val, 1) << 8 | get_byte(val, 0);
173    }
174  }
175  uint16_t pull_val(const uint16_t& val) const {
176    return same_endianness() ? val : pull_val(&val);
177  }
178  int16_t pull_val(const int16_t* val) const {
179    return static_cast<int16_t>
180              (pull_val(reinterpret_cast<const uint16_t*>(val)));
181  }
182  int16_t pull_val(const int16_t& val) const {
183    return static_cast<int16_t>
184              (pull_val(reinterpret_cast<const uint16_t&>(val)));
185  }
186
187  /* Pulls four byte value from ELF file.
188   * Param:
189   *  val - References value inside ELF file buffer to pull data from.
190   * Return
191   *  Pulled value with endianness appropriate for the CPU this library is
192   *  running on.
193   */
194  uint32_t pull_val(const uint32_t* val) const {
195    if (same_endianness()) {
196      return *val;
197    }
198    if (is_elf_big_endian()) {
199      return (uint32_t)get_byte(val, 0) << 24 |
200             (uint32_t)get_byte(val, 1) << 16 |
201             (uint32_t)get_byte(val, 2) << 8  |
202             (uint32_t)get_byte(val, 3);
203    } else {
204      return (uint32_t)get_byte(val, 3) << 24 |
205             (uint32_t)get_byte(val, 2) << 16 |
206             (uint32_t)get_byte(val, 1) << 8  |
207             (uint32_t)get_byte(val, 0);
208    }
209  }
210  uint32_t pull_val(const uint32_t& val) const {
211    return same_endianness() ? val : pull_val(&val);
212  }
213  int32_t pull_val(const int32_t* val) const {
214    return static_cast<int32_t>
215              (pull_val(reinterpret_cast<const uint32_t*>(val)));
216  }
217  int32_t pull_val(const int32_t& val) const {
218    return static_cast<int32_t>
219              (pull_val(reinterpret_cast<const uint32_t&>(val)));
220  }
221
222  /* Pulls eight byte value from ELF file.
223   * Param:
224   *  val - References value inside ELF file buffer to pull data from.
225   * Return
226   *  Pulled value with endianness appropriate for the CPU this library is
227   *  running on.
228   */
229  uint64_t pull_val(const uint64_t* val) const {
230    if (same_endianness()) {
231      return *val;
232    }
233    if (is_elf_big_endian()) {
234      return (uint64_t)get_byte(val, 0) << 56 |
235             (uint64_t)get_byte(val, 1) << 48 |
236             (uint64_t)get_byte(val, 2) << 40 |
237             (uint64_t)get_byte(val, 3) << 32 |
238             (uint64_t)get_byte(val, 4) << 24 |
239             (uint64_t)get_byte(val, 5) << 16 |
240             (uint64_t)get_byte(val, 6) << 8  |
241             (uint64_t)get_byte(val, 7);
242    } else {
243      return (uint64_t)get_byte(val, 7) << 56 |
244             (uint64_t)get_byte(val, 6) << 48 |
245             (uint64_t)get_byte(val, 5) << 40 |
246             (uint64_t)get_byte(val, 4) << 32 |
247             (uint64_t)get_byte(val, 3) << 24 |
248             (uint64_t)get_byte(val, 2) << 16 |
249             (uint64_t)get_byte(val, 1) << 8  |
250             (uint64_t)get_byte(val, 0);
251    }
252  }
253  uint64_t pull_val(const uint64_t& val) const {
254    return same_endianness() ? val : pull_val(&val);
255  }
256  int64_t pull_val(const int64_t* val) const {
257    return static_cast<int64_t>
258              (pull_val(reinterpret_cast<const uint64_t*>(val)));
259  }
260  int64_t pull_val(const int64_t& val) const {
261    return static_cast<int64_t>
262              (pull_val(reinterpret_cast<const uint64_t&>(val)));
263  }
264
265//=============================================================================
266// ELF file section management.
267//=============================================================================
268
269 public:
270  /* Gets a string contained in ELF's string section by index.
271   * Param:
272   *  index - String index (byte offset) in the ELF's string section.
273   * Return:
274   *  Pointer to the requested string, or NULL if string index exceeds ELF's
275   *  string section size.
276   *  NOTE: pointer returned from this method points to a mapped section of
277   *  ELF file.
278   */
279  const char* get_str_sec_str(Elf_Xword index) const {
280    assert(string_section_.is_mapped() && index < string_section_.size());
281    if (string_section_.is_mapped() && index < string_section_.size()) {
282      return INC_CPTR_T(char, string_section_.data(), index);
283    } else {
284      _set_errno(EINVAL);
285      return NULL;
286    }
287  }
288
289  /* Gets a string contained in ELF's debug string section (.debug_str)
290   * by index.
291   * Param:
292   *  index - String index (byte offset) in the ELF's debug string section.
293   * Return:
294   *  Pointer to the requested string, or NULL if string index exceeds ELF's
295   *  debug string section size.
296   *  NOTE: pointer returned from this method points to a mapped section of
297   *  ELF file.
298   */
299  const char* get_debug_str(Elf_Xword index) const {
300    assert(debug_str_.is_mapped() && index < debug_str_.size());
301    if (debug_str_.is_mapped() && index < debug_str_.size()) {
302      return INC_CPTR_T(char, debug_str_.data(), index);
303    } else {
304      _set_errno(EINVAL);
305      return NULL;
306    }
307  }
308
309 protected:
310  /* Gets pointer to a section header, given section index within ELF's
311   * section table.
312   * Param:
313   *  index - Section index within ELF's section table.
314   * Return:
315   *  Pointer to a section header (ElfXX_SHdr flavor, depending on ELF's CPU
316   *  architecture) on success, or NULL if section index exceeds number of
317   *  sections for this ELF file.
318   */
319  const void* get_section_by_index(Elf_Half index) const {
320    assert(index < sec_count_);
321    if (index < sec_count_) {
322      return INC_CPTR(sec_table_, static_cast<size_t>(index) * sec_entry_size_);
323    } else {
324      _set_errno(EINVAL);
325      return NULL;
326    }
327  }
328
329//=============================================================================
330// DWARF management.
331//=============================================================================
332
333 protected:
334  /* Parses DWARF, and buids a list of compilation units for this ELF file.
335   * Compilation unit, collected with this methods are linked together in a
336   * list, head of which is available via last_cu() method of this class.
337   * NOTE: CUs in the list returned via last_cu() method are in reverse order
338   * relatively to the order in which CUs are stored in .debug_info section.
339   * This is ELF and DWARF data format - dependent method.
340   * Param:
341   *  parse_context - Parsing context that defines which tags, and which
342   *    properties for which tag should be collected during parsing. NULL
343   *    passed in this parameter indicates that all properties for all tags
344   *    should be collected.
345   * Return:
346   *  Number of compilation units, collected in this method on success,
347   *  or -1 on failure.
348   */
349  virtual int parse_compilation_units(const DwarfParseContext* parse_context) = 0;
350
351 public:
352  /* Gets PC address information.
353   * Param:
354   *  address - PC address to get information for. The address must be relative
355   *    to the beginning of ELF file represented by this class.
356   *  address_info - Upon success contains information about routine(s) that
357   *    contain the given address.
358   * Return:
359   *  true if routine(s) containing has been found and its information has been
360   *  saved into address_info, or false if no appropriate routine for that
361   *  address has been found, or there was a memory error when collecting
362   *  routine(s) information. In case of failure, errno contains extended error
363   *  information.
364   */
365  bool get_pc_address_info(Elf_Xword address, Elf_AddressInfo* address_info);
366
367  /* Frees resources aqcuired for address information in successful call to
368   * get_pc_address_info().
369   * Param:
370   *  address_info - Address information structure, initialized in successful
371   *    call to get_pc_address_info() routine.
372   */
373  void free_pc_address_info(Elf_AddressInfo* address_info) const;
374
375  /* Gets beginning of the .debug_info section data.
376   * Return:
377   *  Beginning of the .debug_info section data.
378   *  NOTE: pointer returned from this method points to a mapped section of
379   *  ELF file.
380   */
381  const void* get_debug_info_data() const {
382    return debug_info_.data();
383  }
384
385  /* Gets beginning of the .debug_abbrev section data.
386   * Return:
387   *  Beginning of the .debug_abbrev section data.
388   *  NOTE: pointer returned from this method points to a mapped section of
389   *  ELF file.
390   */
391  const void* get_debug_abbrev_data() const {
392    return debug_abbrev_.data();
393  }
394
395  /* Gets beginning of the .debug_ranges section data.
396   * Return:
397   *  Beginning of the .debug_ranges section data.
398   *  NOTE: pointer returned from this method points to a mapped section of
399   *  ELF file.
400   */
401  const void* get_debug_ranges_data() const {
402    return debug_ranges_.data();
403  }
404
405  /* Gets beginning of the .debug_line section data.
406   * Return:
407   *  Beginning of the .debug_line section data.
408   *  NOTE: pointer returned from this method points to a mapped section of
409   *  ELF file.
410   */
411  const void* get_debug_line_data() const {
412    return debug_line_.data();
413  }
414
415  /* Checks, if given address range is contained in the mapped .debug_info
416   * section of this file.
417   * Param:
418   *  ptr - Starting address of the range.
419   *  size - Range size in bytes.
420   * Return:
421   *  true if given address range is contained in the mapped .debug_info
422   *  section of this file, or false if any part of the range doesn't belong
423   *  to that section.
424   */
425  bool is_valid_die_ptr(const void* ptr, size_t size) const {
426    return debug_info_.is_contained(ptr, size);
427  }
428
429  /* Checks, if given address range is contained in the mapped .debug_abbrev
430   * section of this file.
431   * Param:
432   *  ptr - Starting address of the range.
433   *  size - Range size in bytes.
434   * Return:
435   *  true if given address range is contained in the mapped .debug_abbrev
436   *  section of this file, or false if any part of the range doesn't belong
437   *  to that section.
438   */
439  bool is_valid_abbr_ptr(const void* ptr, size_t size) const {
440    return debug_abbrev_.is_contained(ptr, size);
441  }
442
443  /* Checks if given pointer addresses a valid compilation unit header in the
444   * mapped .debug_info section of the ELF file.
445   * Param:
446   *  cu_header - Pointer to a compilation unit header to check.
447   * Return
448   *  true, if given pointer addresses a valid compilation unit header, or
449   *  false, if it's not. A valid CU header must be fully conained inside
450   *  .debug_info section of the ELF file, and its size must not be zero.
451   */
452  bool is_valid_cu(const void* cu_header) const {
453    if (is_DWARF_64()) {
454      return is_valid_die_ptr(cu_header, sizeof(Dwarf64_CUHdr)) &&
455             reinterpret_cast<const Dwarf64_CUHdr*>(cu_header)->size_hdr.size != 0;
456    } else {
457      return is_valid_die_ptr(cu_header, sizeof(Dwarf32_CUHdr)) &&
458             reinterpret_cast<const Dwarf32_CUHdr*>(cu_header)->size_hdr.size != 0;
459    }
460  }
461
462  /* Gets range's low and high pc for the given range reference in the mapped
463   * .debug_ranges section of an ELF file.
464   * Template param:
465   *  AddrType - Defines pointer type for the CU the range belongs to. CU's
466   *    pointer type can be defined independently from ELF and DWARF types,
467   *    and is encoded in address_size field of the CU header in .debug_info
468   *    section of ELF file.
469   * Param:
470   *  offset - Byte offset within .debug_ranges section of the range record.
471   *  low - Upon successful return contains value for range's low pc.
472   *  high - Upon successful return contains value for range's high pc.
473   * Return:
474   *  true on success, or false, if requested record is not fully contained
475   *  in the .debug_ranges section.
476   */
477  template<typename AddrType>
478  bool get_range(Elf_Word offset, AddrType* low, AddrType* high) {
479    const AddrType* ptr = INC_CPTR_T(AddrType, debug_ranges_.data(), offset);
480    assert(debug_ranges_.is_contained(ptr, sizeof(AddrType) * 2));
481    if (!debug_ranges_.is_contained(ptr, sizeof(AddrType) * 2)) {
482      _set_errno(EINVAL);
483      return false;
484    }
485    *low = pull_val(ptr);
486    *high = pull_val(ptr + 1);
487    return true;
488  }
489
490 protected:
491  /* Mapped ELF string section. */
492  ElfMappedSection    string_section_;
493
494  /* Mapped .debug_info section. */
495  ElfMappedSection    debug_info_;
496
497  /* Mapped .debug_abbrev section. */
498  ElfMappedSection    debug_abbrev_;
499
500  /* Mapped .debug_str section. */
501  ElfMappedSection    debug_str_;
502
503  /* Mapped .debug_line section. */
504  ElfMappedSection    debug_line_;
505
506  /* Mapped .debug_ranges section. */
507  ElfMappedSection    debug_ranges_;
508
509  /* Base address of the loaded module (if fixed), or 0 if module doesn't get
510   * loaded at fixed address. */
511  Elf_Xword           fixed_base_address_;
512
513  /* Handle to the ELF file represented with this instance. */
514  MapFile*            elf_handle_;
515
516  /* Path to the ELF file represented with this instance. */
517  char*               elf_file_path_;
518
519  /* DWARF objects allocator for this instance. */
520  class ElfAllocator* allocator_;
521
522  /* Beginning of the cached ELF's section table. */
523  void*               sec_table_;
524
525  /* Number of sections in the ELF file wrapped by this instance. */
526  Elf_Half            sec_count_;
527
528  /* Byte size of an entry in the section table. */
529  Elf_Half            sec_entry_size_;
530
531  /* Head of compilation unit list, collected during the parsing. */
532  class DwarfCU*      last_cu_;
533
534  /* Number of compilation units in last_cu_ list. */
535  int                 cu_count_;
536
537  /* Flags ELF's CPU architecture: 64 (true), or 32 bits (false). */
538  bool                is_ELF_64_;
539
540  /* Flags endianness of the processed ELF file. true indicates that ELF file
541   * data is stored in big-endian form, false indicates that ELF file data is
542   * stored in big-endian form.
543   */
544  bool                is_elf_big_endian_;
545
546  /* Flags whether or not endianness of CPU this library is built for matches
547   * endianness of the ELF file that is represented with this instance.
548   */
549  bool                same_endianness_;
550
551  /* Flags DWARF format: 64, or 32 bits. DWARF format is determined by looking
552   * at the first 4 bytes of .debug_info section (which is the beginning of the
553   * first compilation unit header). If first 4 bytes contain 0xFFFFFFFF, the
554   * DWARF is 64 bit. Otherwise, DWARF is 32 bit. */
555  bool                is_DWARF_64_;
556
557  /* Flags executable file. If this member is 1, ELF file represented with this
558   * instance is an executable. If this member is 0, file is a shared library.
559   */
560  bool                is_exec_;
561};
562
563/* Encapsulates architecture-dependent functionality of an ELF file.
564 * Template param:
565 *  Elf_Addr - type for an address field in ELF file. Must be:
566 *    - Elf32_Addr for 32-bit CPU, or
567 *    - Elf64_Addr for 64-bit CPU.
568 *  Elf_Off - type for an offset field in ELF file. Must be:
569 *    - Elf64_Off for 32-bit CPU, or
570 *    - Elf64_Off for 64-bit CPU.
571 */
572template <typename Elf_Addr, typename Elf_Off>
573class ElfFileImpl : protected ElfFile {
574/* Instance of this class must be instantiated from
575 * ElfFile::Create() method only. */
576friend class ElfFile;
577 protected:
578  /* Constructs ElfFileImpl instance. */
579  ElfFileImpl() {
580  };
581
582  /* Destructs ElfFileImpl instance. */
583  ~ElfFileImpl() {
584  }
585
586 protected:
587  /* Initializes instance. This is an override of the base class method.
588   * See ElfFile::initialize().
589   */
590  bool initialize(const Elf_CommonHdr* elf_hdr, const char* path);
591
592  /* Parses DWARF, and buids list of compilation units for this ELF file.
593   * This is an implementation of the base class' abstract method.
594   * See ElfFile::parse_compilation_units().
595   */
596  virtual int parse_compilation_units(const DwarfParseContext* parse_context);
597
598  /* Gets section information by section name.
599   * Param:
600   *  name - Name of the section to get information for.
601   *  offset - Upon success contains offset of the section data in ELF file.
602   *  size - Upon success contains size of the section data in ELF file.
603   * Return:
604   *  true on sucess, or false if section with such name doesn't exist in
605   *  this ELF file.
606   */
607  bool get_section_info_by_name(const char* name,
608                                Elf_Off* offset,
609                                Elf_Word* size);
610
611  /* Maps section by its name.
612   * Param:
613   *  name - Name of the section to map.
614   *  section - Upon success contains section's mapping information.
615   * Return:
616   *  true on sucess, or false if section with such name doesn't exist in
617   *  this ELF file, or mapping has failed.
618   */
619  bool map_section_by_name(const char* name, ElfMappedSection* section);
620};
621
622#endif  // ELFF_ELF_FILE_H_
623