Home | History | Annotate | Download | only in elff
      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 "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  */
     35 class 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  */
    572 template <typename Elf_Addr, typename Elf_Off>
    573 class ElfFileImpl : protected ElfFile {
    574 /* Instance of this class must be instantiated from
    575  * ElfFile::Create() method only. */
    576 friend 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