/* Copyright (C) 2007-2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
*/

/*
 * Contains declarations of classes defined for a variety of DWARF objects.
 */

#ifndef ELFF_DWARF_DIE_H_
#define ELFF_DWARF_DIE_H_

#include "dwarf_defs.h"
#include "elf_alloc.h"

class ElfFile;
class DwarfCU;

/* Encapsulates an object that wraps up a DIE, cached during
 * ELF file parsing.
 */
class DIEObject : public DwarfAllocBase {
 public:
  /* Constructs DIEObject intance.
   * Param:
   *  die - DIE represented with this instance.
   *  parent_cu - Compilation unit this DIE belongs to.
   *  parent_die - Parent DIE object for this DIE. This parameter can be NULL
   *    only for compilation unit DIEs.
   */
  DIEObject(const Dwarf_DIE* die, DwarfCU* parent_cu, DIEObject* parent_die)
      : die_(die),
        parent_cu_(parent_cu),
        parent_die_(parent_die),
        last_child_(NULL),
        prev_sibling_(NULL) {
  }

  /* Destructs DIEObject intance. */
  ~DIEObject();

  /* Gets ELF file this DIE belongs to. */
  ElfFile* elf_file() const;

  /* Gets DWARF tag (DW_TAG_Xxx) for the DIE represented with this instance. */
  Dwarf_Tag get_tag() const;

  /* Gets the best name for this DIE.
   * Some DIEs (such as inline routine DIEs) may have no DW_AT_name property,
   * but may reference to another DIE that may contain DIE name. This method
   * tries its best to get DIE name by iterating through different methods of
   * naming the DIE.
   * Return:
   *  Name for this DIE, or NULL if it was not possible to find a relevant DIE
   *  with DW_AT_name property.
   */
  const char* get_name() const;

  /* Gets DIE's attribute by its ID.
   * Param:
   *  at_id - ID (DW_AT_Xxx) of the attribute to get.
   *  attr - Upon successful return contains requested attribute information.
   * Return:
   *  true on success, or false if attribute for the given ID doesn't exist
   *  in the DIE's attribute list.
   */
  bool get_attrib(Dwarf_At at, DIEAttrib* attr) const;

  /* Gets the leaf DIE object containing given address.
   * See DwarfCU::get_leaf_die_for_address() for method details.
   * See DIEObject::contains_address() for implementation details.
   */
  DIEObject* get_leaf_for_address(Elf_Xword address);

  /* Finds a DIE object for the given die in the branch starting with
   * this DIE object.
   */
  DIEObject* find_die_object(const Dwarf_DIE* die_to_find);

  /* Dumps this object to stdout.
   * Param:
   *  only_this - If true, only this object will be dumped. If this parameter
   *    is false, all the childs and siblings of this object will be dumped
   *    along with this object.
   */
  void dump(bool only_this) const;

 protected:
  /* Checks if this DIE object containing given address.
   * Template param:
   *  AddrType - Type of compilation unin address (4, or 8 bytes), defined by
   *    address_size field of the CU header. Must be Elf_Xword for 8 bytes
   *    address, or Elf_Word for 4 bytes address.
   * Param:
   *  address - Address ti check.
   * Return:
   *  True, if this DIE address ranges (including low_pc, high_pc attributes)
   *  contain given address, or false otherwise.
   */
  template <typename AddrType>
  bool contains_address(Elf_Xword address);

  /* Advances to the DIE's property list.
   * Param:
   *  at_abbr - Upon successful return contains a pointer to the beginning of
   *    DIE attribute abbreviation list. This parameter can be NULL, if the
   *    caller is not interested in attribute abbreviation list for this DIE.
   *  tag - Upon successful return contains DIE's tag. This parameter can be
   *    NULL, if the caller is not interested in the tag value for this DIE.
   * Return:
   *  Pointer to the beginning of the DIE attribute list in mapped .debug_info
   *  section on success, or NULL on failure.
   */
  const Elf_Byte* advance(const Dwarf_Abbr_AT** at_abbr, Dwarf_Tag* tag) const;

 public:
  /* Gets DIE represented with this instance. */
  const Dwarf_DIE* die() const {
    return die_;
  }

  /* Gets compilation unit this DIE belongs to. */
  DwarfCU* parent_cu() const {
    return parent_cu_;
  }

  /* Gets parent DIE object for this die. */
  DIEObject* parent_die() const {
    return parent_die_;
  }

  /* Gets last child object in the list of this DIE's childs. NOTE: for better
   * performace the list is created in reverse order (relatively to the order,
   * in which children DIEs have been discovered).
   */
  DIEObject* last_child() const {
    return last_child_;
  }

  /* Links next child to the list of this DIE childs. */
  void link_child(DIEObject* child) {
    last_child_ = child;
  }

  /* Gets previous sibling of this DIE in the parent's DIE object list. */
  DIEObject* prev_sibling() const {
    return prev_sibling_;
  }

  /* Links next sibling to the list of this DIE siblings. */
  void link_sibling(DIEObject* sibl) {
    prev_sibling_ = sibl;
  }

  /* Checks if this DIE object represents a CU DIE.
   * We relay here on the fact that only CU DIE objects have no parent
   * DIE objects.
   */
  bool is_cu_die() const {
    return parent_die_ == NULL;
  }

  /* Gets this DIE level in the branch.
   * DIE level defines DIE's distance from the CU DIE in the branch this DIE
   * belongs to. In other words, DIE level defines how many parent DIEs exist
   * between this DIE, and the CU DIE. For instance, the CU DIE has level 0,
   * a subroutine a() in this compilation unit has level 1, a soubroutine b(),
   * that has been inlined into subroutine a() will have level 2, a try/catch
   * block in the inlined subroutine b() will have level 3, and so on.
   */
  Elf_Word get_level() const {
    return parent_die_ != NULL ? parent_die_->get_level() + 1 : 0;
  }

 protected:
  /* DIE that is represented with this instance. */
  const Dwarf_DIE*  die_;

  /* Compilation unit this DIE belongs to. */
  DwarfCU*          parent_cu_;

  /* Parent DIE object for this die. */
  DIEObject*        parent_die_;

  /* Last child object in the list of this DIE's childs. NOTE: for better
   * performace the list is created in reverse order (relatively to the order,
   * in which children DIEs have been discovered).
   */
  DIEObject*        last_child_;

  /* Previous sibling of this DIE in the parent's DIE object list. */
  DIEObject*        prev_sibling_;
};

#endif  // ELFF_DWARF_DIE_H_
