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 a class DwarfCU, that encapsulates a compilation
     15  * unit in the .debug_info section of the mapped ELF file.
     16  */
     17 
     18 #ifndef ELFF_DWARF_CU_H_
     19 #define ELFF_DWARF_CU_H_
     20 
     21 #include "dwarf_defs.h"
     22 #include "dwarf_die.h"
     23 
     24 /* Address information descriptor. */
     25 typedef struct Dwarf_AddressInfo {
     26   /* Routine DIE containing the address. */
     27   const DIEObject*  die_obj;
     28 
     29   /* Source file name for the address. */
     30   const char*       file_name;
     31 
     32   /* Source file directory path for the address. */
     33   const char*       dir_name;
     34 
     35   /* Source file line number for the address. */
     36   Elf_Word          line_number;
     37 } Dwarf_AddressInfo;
     38 
     39 /* STMTL header cached by compilation unit. This header is contained in
     40  * the .debug_line section of the ELF file. */
     41 typedef struct Dwarf_STMTL_Hdr {
     42   /* The size in bytes of the line number information for this compilation
     43    * unit, not including the unit_length field itself. */
     44   Elf_Xword                   unit_length;
     45 
     46   /* A version number. This number is specific to the line number information
     47    * and is independent of the DWARF version number. */
     48   Elf_Half                    version;
     49 
     50   /* The number of bytes following the header_length field to the beginning of
     51    * the first byte of the line number program itself. In the 32-bit DWARF
     52    * format, this is a 4-byte unsigned length; in the 64-bit DWARF format,
     53    * this field is an 8-byte unsigned length. */
     54   Elf_Xword                   header_length;
     55 
     56   /* The size in bytes of the smallest target machine instruction. Line number
     57    * program opcodes that alter the address register first multiply their
     58    * operands by this value. */
     59   Elf_Byte                    min_instruction_len;
     60 
     61   /* The initial value of the is_stmt register. */
     62   Elf_Byte                    default_is_stmt;
     63 
     64   /* This parameter affects the meaning of the special opcodes. */
     65   Elf_Sbyte                   line_base;
     66 
     67   /* This parameter affects the meaning of the special opcodes. */
     68   Elf_Byte                    line_range;
     69 
     70   /* The number assigned to the first special opcode. */
     71   Elf_Byte                    opcode_base;
     72 
     73   /* Points to standard_opcode_lengths array in the actual STMTL header in
     74    * the mapped .debug_line section. */
     75   const Elf_Byte*             standard_opcode_lengths;
     76 
     77   /* Pointer to the beginning of the list of include directories in the mapped
     78    * .debug_line section. */
     79   const char*                 include_directories;
     80 
     81   /* Number of include directories in the list that begins with
     82    * include_directories. */
     83   Elf_Word                    inc_dir_num;
     84 
     85   /* Pointer to the beginning of the list of file information in the mapped
     86    * .debug_line section. Each entry in this list begins with zero-terminated
     87    * file name, followed by ULEB128 encoding directory index for the file,
     88    * followed by ULEB128 encoding last modification time, followed by ULEB128
     89    * encoding length of file in bytes. */
     90   const Dwarf_STMTL_FileDesc* file_infos;
     91 
     92   /* Start of the "Line Number Program" in the mapped .debug_line section. */
     93   const Elf_Byte*             start;
     94 
     95   /* End of the "Line Number Program" in the mapped .debug_line section. */
     96   const Elf_Byte*             end;
     97 } Dwarf_STMTL_Hdr;
     98 
     99 /* Encapsulates architecture-independent functionality of a
    100  * compilation unit.
    101  */
    102 class DwarfCU : public DwarfAllocBase {
    103 friend class ElfFile;
    104  public:
    105   /* Constructs DwarfCU instance.
    106    * Param:
    107    *  elf - Instance of ElfFile containing this compilation unit.
    108    */
    109   explicit DwarfCU(ElfFile* elf);
    110 
    111   /* Destructs DwarfCU instance. */
    112   virtual ~DwarfCU();
    113 
    114   /* Creates DwarfCUImpl instance, depending on DWARF format.
    115    * Param:
    116    *  elf - Instance of ElfFile containing this compilation unit.
    117    *  hdr - Pointer to compilation unit header inside mapped .debug_info
    118    *    section of the ELF file. Actual data addressed by this pointer
    119    *    must be Dwarf32_CUHdr for 32 bit DWARFs, or Dwarf64_CUHdr for
    120    *    64 bit DWARFs.
    121    * Return:
    122    *  Created DwarfCUImpl instance (typecasted back to DwarfCU) on success,
    123    *  or NULL on failure.
    124    */
    125   static DwarfCU* create_instance(ElfFile* elf, const void* hdr);
    126 
    127   /* Process a DIE attribute.
    128    * Param:
    129    *  attr - Attribute list inside the mapped .debug_info section of the ELF
    130    *    file.
    131    *  form - Attribute's form, definig representation of attribute value in the
    132    *    mapped .debug_info section of the ELF file.
    133    *  attr_value - Upon return contains attribute value.
    134    * Return:
    135    *  Pointer to the next DIE attribute inside the mapped .debug_info section
    136    *  of the ELF file.
    137    */
    138   const Elf_Byte* process_attrib(const Elf_Byte* attr,
    139                                  Dwarf_Form form,
    140                                  Dwarf_Value* attr_value) const;
    141 
    142   /* Dumps this compilation unit to the stdout. */
    143   void dump() const;
    144 
    145   /* Gets instance of ElfFile containing this compilation unit. */
    146   ElfFile* elf_file() const {
    147     return elf_file_;
    148   }
    149 
    150   /* Gets DIE object for this CU. */
    151   DIEObject* cu_die() const {
    152     return cu_die_;
    153   }
    154 
    155   /* Gets byte size of the pointer type for this compilation unit. */
    156   Elf_Byte addr_sizeof() const {
    157     return addr_sizeof_;
    158   }
    159 
    160   /* Gets full path to the compilation directory (DW_AT_comp_dir attribute).
    161    * Return:
    162    *  Full path to the compilation directory (DW_AT_comp_dir attribute),
    163    *  or NULL, if that attribute was missing in CU's attribute list.
    164    */
    165   const char* comp_dir_path() const {
    166     DIEAttrib attr;
    167     return cu_die()->get_attrib(DW_AT_comp_dir, &attr) ? attr.value()->str :
    168                                                          NULL;
    169   }
    170 
    171   /* Gets relative (from the compilation directory) path to the compiled file.
    172    * (DW_AT_name attribute).
    173    * Return:
    174    *  Relative path to the compiled file (DW_AT_name attribute), or NULL, if
    175    *  that attribute was missing in CU's attribute list.
    176    */
    177   const char* rel_cu_path() const {
    178     DIEAttrib attr;
    179     return cu_die()->get_attrib(DW_AT_name, &attr) ? attr.value()->str :
    180                                                      NULL;
    181   }
    182 
    183   /* Gets next compilation unit in the list. NULL indicates the last CU. */
    184   DwarfCU* prev_cu() const {
    185     return prev_cu_;
    186   }
    187 
    188   /* Links this CU to the list of prevoiusly discovered CUs. */
    189   void set_prev_cu(DwarfCU* prev) {
    190     prev_cu_ = prev;
    191   }
    192 
    193   /* Checks if DWARF version for this CU is higher than 2. */
    194   bool is_DWARF3_or_higher() const {
    195     return version_ >= 3;
    196   }
    197 
    198   /* Gets DIE abbreviation for given abbreviation number.
    199    * See DwarfAbbrDieArray::get() */
    200   const Dwarf_Abbr_DIE* get_die_abbr(Dwarf_AbbrNum num) const {
    201     return abbrs_.get(num);
    202   }
    203 
    204   /* Gets DIE object containing given address.
    205    * DIE address ranges may overlap (for instance, address range for an inlined
    206    * routine will be contained within the address range of a routine where it
    207    * was inlined). This method will return a DIE object that is a "leaf" in
    208    * that inlining tree. I.e the returned DIE object represents the last DIE
    209    * in the branch of all DIEs containing given address.
    210    * Param:
    211    *  address - Address to get a DIE for. NOTE: for the sake of simplicity we
    212    *    explicitly use 64-bit type for an address.
    213    * Return:
    214    *  Leaf DIE containing given address, or NULL if this CU doesn't contain
    215    *  the given address.
    216    */
    217   DIEObject* get_leaf_die_for_address(Elf_Xword address) const {
    218     return cu_die_->get_leaf_for_address(address);
    219   }
    220 
    221   /* Checks if this CU contains 64, or 32-bit addresses. */
    222   bool is_CU_address_64() const {
    223     return addr_sizeof_ == 8;
    224   }
    225   bool is_CU_address_32() const {
    226     return addr_sizeof_ == 4;
    227   }
    228 
    229 //=============================================================================
    230 // DWARF format dependent methods
    231 //=============================================================================
    232 
    233  public:
    234   /* Parses this compilation unit in .debug_info section, collecting children
    235    * DIEs of this compilation unit.
    236    * Param:
    237    *  parse_context - Parsing context that lists tags for DIEs that should be
    238    *    collected during parsing. NULL passed in this parameter indicates DIEs
    239    *    for all tags should be collected.
    240    *  next_cu_die - Upon successful return contains pointer to the next
    241    *    compilation unit descriptor inside mapped .debug_info section of
    242    *    the ELF file.
    243    * Return:
    244    *  true on success, false on failure.
    245    */
    246   virtual bool parse(const DwarfParseContext* parse_context,
    247                      const void** next_cu_die) = 0;
    248 
    249   /* Gets a DIE object referenced by an offset from the beginning of
    250    * this CU in the mapped .debug_info section.
    251    */
    252   virtual DIEObject* get_referenced_die_object(Elf_Word ref) const = 0;
    253 
    254   /* Gets a reference to a DIE object (offset of the DIE from the
    255    * beginning of this CU in the mapped .debug_info section.
    256    */
    257   virtual Elf_Word get_die_reference(const Dwarf_DIE* die) const = 0;
    258 
    259   /* Gets PC address information.
    260    * Param:
    261    *  address - PC address to get information for.
    262    *  info - Upon success contains information about routine that belongs to
    263    *    this compilation unit, containing the given address.
    264    * Return:
    265    *  true on success, or false if this CU doesn't contain the given address.
    266    */
    267   virtual bool get_pc_address_file_info(Elf_Xword address,
    268                                         Dwarf_AddressInfo* info) = 0;
    269 
    270   /* Gets file descriptor in the mapped .debug_line section of ELF file for a
    271    * given index in the file descriptor list.
    272    * Param:
    273    *  index - 1-based index of file descriptor in the file descriptor list.
    274    * Return:
    275    *  File descriptor for the given index, or NULL if index was too big.
    276    *  NOTE: pointer returned from this method addressed mapped section of
    277    *  ELF file.
    278    */
    279   virtual const Dwarf_STMTL_FileDesc* get_stmt_file_info(Elf_Word index) = 0;
    280 
    281   /* Gets directory name by an index in the mapped .debug_line section of
    282    * ELF file.
    283    * Param:
    284    *  dir_index - Index of the directory in the file descriptor list. If this
    285    *    parameter is zero, compilation directory (DW_AT_comp_dir) for this CU
    286    *    will be returned.
    287    * Return:
    288    *  Directory name for the given index, or NULL if index was too big.
    289    *  NOTE: pointer returned from this method addressed mapped section of
    290    *  ELF file.
    291    */
    292   virtual const char* get_stmt_dir_name(Elf_Word dir_index) = 0;
    293 
    294  protected:
    295   /* DIE abbreviation descriptors, cached for this compilation unit. */
    296   DwarfAbbrDieArray   abbrs_;
    297 
    298   /* Instance of an ELF file that contains this compilation unit. */
    299   ElfFile*            elf_file_;
    300 
    301   /* DIE object for this CU. */
    302   DIEObject*          cu_die_;
    303 
    304   /* Next compilation unit in the list (previous in the order they've been
    305    * discovered during ELF file parsing).
    306    */
    307   DwarfCU*            prev_cu_;
    308 
    309   /* DWARF version for this CU. */
    310   Elf_Half            version_;
    311 
    312   /* Byte size of the pointer type for this compilation unit. */
    313   Elf_Byte            addr_sizeof_;
    314 };
    315 
    316 /* Encapsulates architecture-dependent functionality of a compilation unit.
    317  * Template param:
    318  *  Dwarf_CUHdr - type compilation unit header in the mapped .debug_info
    319  *    section of ELF file. Must be:
    320  *    - Dwarf32_CUHdr for 32-bit DWARF, or
    321  *    - Dwarf64_CUHdr for 64-bit DWARF.
    322  *  Dwarf_Off - type for an offset field in DWARF data format. Must be:
    323  *    - Dwarf32_Off for 32-bit DWARF, or
    324  *    - Dwarf64_Off for 64-bit DWARF.
    325  */
    326 template <typename Dwarf_CUHdr, typename Dwarf_Off>
    327 class DwarfCUImpl : public DwarfCU {
    328  public:
    329   /* Constructs DwarfCU instance.
    330    * Param:
    331    *  elf - Instance of ElfFile containing this compilation unit.
    332    *  hdr - Pointer to compilation unit header inside mapped .debug_info
    333    *    section of the ELF file.
    334    */
    335   DwarfCUImpl(ElfFile* elf, const Dwarf_CUHdr* hdr);
    336 
    337   /* Destructs DwarfCU instance. */
    338   ~DwarfCUImpl() {
    339   }
    340 
    341   /* Parses this compilation unit in .debug_info section, collecting children
    342    * DIEs of this compilation unit. This is an implementation of DwarfCU's
    343    * abstract metod.
    344    * See DwarfCU::parse().
    345    */
    346   bool parse(const DwarfParseContext* parse_context,
    347              const void** next_cu_die);
    348 
    349   /* Gets PC address information.
    350    * This is an implementation of DwarfCU's abstract metod.
    351    * See DwarfCU::get_pc_address_file_info().
    352    */
    353   bool get_pc_address_file_info(Elf_Xword address, Dwarf_AddressInfo* info);
    354 
    355   /* Gets file descriptor in the mapped .debug_line section of ELF file for a
    356    * given index in the file descriptor list.
    357    * This is an implementation of DwarfCU's abstract metod.
    358    * See DwarfCU::get_stmt_file_info().
    359    */
    360   const Dwarf_STMTL_FileDesc* get_stmt_file_info(Elf_Word index);
    361 
    362   /* Gets directory name by an index in the mapped .debug_line section of
    363    * ELF file.
    364    * This is an implementation of DwarfCU's abstract metod.
    365    * See DwarfCU::get_stmt_dir_name().
    366    */
    367   const char* get_stmt_dir_name(Elf_Word dir_index);
    368 
    369   /* Gets a DIE object referenced by an offset from the beginning of
    370    * this CU. This is an implementation of DwarfCU's abstract metod.
    371    */
    372   DIEObject* get_referenced_die_object(Elf_Word ref) const {
    373     const Dwarf_DIE* die = get_referenced_die(ref);
    374     return cu_die_->find_die_object(die);
    375   }
    376 
    377   /* Gets a reference to a DIE object (offset of the DIE from the
    378    * beginning of this CU in the mapped .debug_info section.
    379    * This is an implementation of DwarfCU's abstract metod.
    380    */
    381   Elf_Word get_die_reference(const Dwarf_DIE* die) const {
    382     return static_cast<Elf_Word>(diff_ptr(cu_header_, die));
    383   }
    384 
    385  protected:
    386   /* Process a child DIE (and all its children) in this compilation unit.
    387    * Param:
    388    *  parse_context - See DwarfCU::parse().
    389    *  die - DIE descriptor of the child to process in this method.
    390    *  parent_obj - Parent object of the child to process in this method.
    391    *    NOTE: this parameter can be NULL only for a DIE that represents this
    392    *    compilation unit itself.
    393    * Return:
    394    *  Pointer to the end of child's attribute list in the mapped .debug_info
    395    *  section on success, or NULL on failure. Usually, pointer returned from
    396    *  this method is simply discarded, since parent calculates address of the
    397    *  next sibling's DIE based on DW_AT_sibling attribute of the DIE preceding
    398    *  child's DIE.
    399    */
    400   const Elf_Byte* process_DIE(const DwarfParseContext* parse_context,
    401                               const Dwarf_DIE* die,
    402                               DIEObject* parent_obj);
    403 
    404   /* Creates a DIE object for the given DIE.
    405    * Param:
    406    *  parse_context See DwarfCU::parse().
    407    *  die - DIE to create an object for.
    408    *  parent - Parent DIE object for the one that's being created in this
    409    *    method.
    410    *  tag - Tag of the DIE object that's being created in this method.
    411    * Return:
    412    *  Created DIE object. This method may returns NULL in two cases:
    413    *    - We're not interested in this DIE (decided by looking at 'tag'
    414    *      parameter. In this case errno should be set to zero.
    415    *    - Memory allocation has failed. In this case errno should be
    416    *      set to ENOMEM.
    417    */
    418   DIEObject* create_die_object(const DwarfParseContext* parse_context,
    419                                const Dwarf_DIE* die,
    420                                DIEObject* parent,
    421                                Dwarf_Tag tag);
    422 
    423   /* Initializes (caches) STMT lines header for this CU. */
    424   bool init_stmtl();
    425 
    426   /* Saves current source file information, collected in the state machine by
    427    * the "Line Number Program".
    428    * Param:
    429    *  state - State machine collected "Line Number Program" results.
    430    *  info - Upon success contains source file information, copied over from
    431    *    the state machine.
    432    * Return:
    433    *  true on success, or false on failure.
    434    */
    435   bool set_source_info(const DwarfStateMachine* state,
    436                        Dwarf_AddressInfo* info);
    437 
    438   /* Gets pointer to the DIE descriptor for this CU. */
    439   const Dwarf_DIE* get_DIE() const {
    440     /* CU's DIE descriptor immediately follows CU header. */
    441     return INC_CPTR_T(Dwarf_DIE, cu_header_, sizeof(Dwarf_CUHdr));
    442   }
    443 
    444   /* Caches STMTL header from .debug_line section to stmtl_header_.
    445    * Template param:
    446    *  Dwarf_STMTL_Hdr - Dwarf_STMTL_Hdr32, or Dwarf_STMTL_Hdr64, depending
    447    *    on the header type.
    448    * Param:
    449    *  stmtl_hdr - STMTL header in the mapped .debug_line section to cache.
    450    */
    451   template <typename Dwarf_STMTL_Hdr>
    452   void cache_stmtl(const Dwarf_STMTL_Hdr* stmtl_hdr) {
    453     stmtl_header_.unit_length = elf_file()->pull_val(stmtl_hdr->unit_length.size);
    454     stmtl_header_.version = elf_file()->pull_val(stmtl_hdr->version);
    455     stmtl_header_.header_length = elf_file()->pull_val(stmtl_hdr->header_length);
    456     stmtl_header_.min_instruction_len = stmtl_hdr->min_instruction_len;
    457     stmtl_header_.default_is_stmt = stmtl_hdr->default_is_stmt;
    458     stmtl_header_.line_base = stmtl_hdr->line_base;
    459     stmtl_header_.line_range = stmtl_hdr->line_range;
    460     stmtl_header_.opcode_base = stmtl_hdr->opcode_base;
    461     stmtl_header_.standard_opcode_lengths = &stmtl_hdr->standard_opcode_lengths;
    462     stmtl_header_.start = INC_CPTR_T(Elf_Byte, &stmtl_hdr->min_instruction_len,
    463                                      stmtl_header_.header_length);
    464     stmtl_header_.end = INC_CPTR_T(Elf_Byte, &stmtl_hdr->version,
    465                                    stmtl_header_.unit_length);
    466     stmtl_header_.include_directories =
    467         INC_CPTR_T(char, stmtl_header_.standard_opcode_lengths,
    468                    stmtl_header_.opcode_base - 1);
    469     const char* dir = stmtl_header_.include_directories;
    470     while (*dir != '\0') {
    471       dir += strlen(dir) + 1;
    472       stmtl_header_.inc_dir_num++;
    473     }
    474     stmtl_header_.file_infos = INC_CPTR_T(Dwarf_STMTL_FileDesc, dir, 1);
    475   }
    476 
    477   /* Gets a DIE referenced by an offset from the beginning of this CU
    478    * in the mapped .debug_info section.
    479    */
    480   const Dwarf_DIE* get_referenced_die(Elf_Word ref) const {
    481     return INC_CPTR_T(Dwarf_DIE, cu_header_, ref);
    482   }
    483 
    484   /* Checks if pointer to the DIE attribute is contained within the CU's area
    485    * of the mapped .debug_info section.
    486    * Param:
    487    *  ptr - Pointer to the DIE attribute to check.
    488    * Return:
    489    *  true, if pointer to the DIE attribute is contained within the CU's area
    490    *  of the mapped .debug_info section, or false if attribute pointer goes
    491    *  beyond CU's area of the mapped .debug_info section.
    492    */
    493   bool is_attrib_ptr_valid(const void* ptr) const {
    494     return diff_ptr(cu_header_, ptr) < cu_size_;
    495   }
    496 
    497  protected:
    498   /* Pointer to this compilation unit header inside the mapped .debug_info
    499    * section of the ELF file.
    500    */
    501   const Dwarf_CUHdr*          cu_header_;
    502 
    503   /* Size of this compilation unit area in the mapped .debug_info section.
    504    * This value has been cached off the CU header in order to avoid
    505    * endianness conversions.
    506    */
    507   Dwarf_Off                   cu_size_;
    508 
    509   /* STMT lines header, cached off mapped .debug_line section. */
    510   Dwarf_STMTL_Hdr             stmtl_header_;
    511 };
    512 
    513 #endif  // ELFF_DWARF_CU_H_
    514