aboutsummaryrefslogtreecommitdiffstats
path: root/elff/dwarf_cu.h
diff options
context:
space:
mode:
authorVladimir Chtchetkine <vchtchetkine@google.com>2010-02-16 10:38:35 -0800
committerVladimir Chtchetkine <vchtchetkine@google.com>2010-02-18 15:22:07 -0800
commit5389aa19033153c09556d1362a8b8a56abccb8f5 (patch)
tree5d731effe5bd5d2f162f06aadec7212045eaef3d /elff/dwarf_cu.h
parent76dbca0489ab98a46f2954bc7b77c3df6f9d8264 (diff)
downloadexternal_qemu-5389aa19033153c09556d1362a8b8a56abccb8f5.zip
external_qemu-5389aa19033153c09556d1362a8b8a56abccb8f5.tar.gz
external_qemu-5389aa19033153c09556d1362a8b8a56abccb8f5.tar.bz2
Merge memory checking from sandbox
Change-id: Ibce845d0
Diffstat (limited to 'elff/dwarf_cu.h')
-rw-r--r--elff/dwarf_cu.h513
1 files changed, 513 insertions, 0 deletions
diff --git a/elff/dwarf_cu.h b/elff/dwarf_cu.h
new file mode 100644
index 0000000..a8f0578
--- /dev/null
+++ b/elff/dwarf_cu.h
@@ -0,0 +1,513 @@
+/* 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 declaration of a class DwarfCU, that encapsulates a compilation
+ * unit in the .debug_info section of the mapped ELF file.
+ */
+
+#ifndef ELFF_DWARF_CU_H_
+#define ELFF_DWARF_CU_H_
+
+#include "dwarf_defs.h"
+#include "dwarf_die.h"
+
+/* Address information descriptor. */
+typedef struct Dwarf_AddressInfo {
+ /* Routine DIE containing the address. */
+ const DIEObject* die_obj;
+
+ /* Source file name for the address. */
+ const char* file_name;
+
+ /* Source file directory path for the address. */
+ const char* dir_name;
+
+ /* Source file line number for the address. */
+ Elf_Word line_number;
+} Dwarf_AddressInfo;
+
+/* STMTL header cached by compilation unit. This header is contained in
+ * the .debug_line section of the ELF file. */
+typedef struct Dwarf_STMTL_Hdr {
+ /* The size in bytes of the line number information for this compilation
+ * unit, not including the unit_length field itself. */
+ Elf_Xword unit_length;
+
+ /* A version number. This number is specific to the line number information
+ * and is independent of the DWARF version number. */
+ Elf_Half version;
+
+ /* The number of bytes following the header_length field to the beginning of
+ * the first byte of the line number program itself. In the 32-bit DWARF
+ * format, this is a 4-byte unsigned length; in the 64-bit DWARF format,
+ * this field is an 8-byte unsigned length. */
+ Elf_Xword header_length;
+
+ /* The size in bytes of the smallest target machine instruction. Line number
+ * program opcodes that alter the address register first multiply their
+ * operands by this value. */
+ Elf_Byte min_instruction_len;
+
+ /* The initial value of the is_stmt register. */
+ Elf_Byte default_is_stmt;
+
+ /* This parameter affects the meaning of the special opcodes. */
+ Elf_Sbyte line_base;
+
+ /* This parameter affects the meaning of the special opcodes. */
+ Elf_Byte line_range;
+
+ /* The number assigned to the first special opcode. */
+ Elf_Byte opcode_base;
+
+ /* Points to standard_opcode_lengths array in the actual STMTL header in
+ * the mapped .debug_line section. */
+ const Elf_Byte* standard_opcode_lengths;
+
+ /* Pointer to the beginning of the list of include directories in the mapped
+ * .debug_line section. */
+ const char* include_directories;
+
+ /* Number of include directories in the list that begins with
+ * include_directories. */
+ Elf_Word inc_dir_num;
+
+ /* Pointer to the beginning of the list of file information in the mapped
+ * .debug_line section. Each entry in this list begins with zero-terminated
+ * file name, followed by ULEB128 encoding directory index for the file,
+ * followed by ULEB128 encoding last modification time, followed by ULEB128
+ * encoding length of file in bytes. */
+ const Dwarf_STMTL_FileDesc* file_infos;
+
+ /* Start of the "Line Number Program" in the mapped .debug_line section. */
+ const Elf_Byte* start;
+
+ /* End of the "Line Number Program" in the mapped .debug_line section. */
+ const Elf_Byte* end;
+} Dwarf_STMTL_Hdr;
+
+/* Encapsulates architecture-independent functionality of a
+ * compilation unit.
+ */
+class DwarfCU : public DwarfAllocBase {
+friend class ElfFile;
+ public:
+ /* Constructs DwarfCU instance.
+ * Param:
+ * elf - Instance of ElfFile containing this compilation unit.
+ */
+ explicit DwarfCU(ElfFile* elf);
+
+ /* Destructs DwarfCU instance. */
+ virtual ~DwarfCU();
+
+ /* Creates DwarfCUImpl instance, depending on DWARF format.
+ * Param:
+ * elf - Instance of ElfFile containing this compilation unit.
+ * hdr - Pointer to compilation unit header inside mapped .debug_info
+ * section of the ELF file. Actual data addressed by this pointer
+ * must be Dwarf32_CUHdr for 32 bit DWARFs, or Dwarf64_CUHdr for
+ * 64 bit DWARFs.
+ * Return:
+ * Created DwarfCUImpl instance (typecasted back to DwarfCU) on success,
+ * or NULL on failure.
+ */
+ static DwarfCU* create_instance(ElfFile* elf, const void* hdr);
+
+ /* Process a DIE attribute.
+ * Param:
+ * attr - Attribute list inside the mapped .debug_info section of the ELF
+ * file.
+ * form - Attribute's form, definig representation of attribute value in the
+ * mapped .debug_info section of the ELF file.
+ * attr_value - Upon return contains attribute value.
+ * Return:
+ * Pointer to the next DIE attribute inside the mapped .debug_info section
+ * of the ELF file.
+ */
+ const Elf_Byte* process_attrib(const Elf_Byte* attr,
+ Dwarf_Form form,
+ Dwarf_Value* attr_value) const;
+
+ /* Dumps this compilation unit to the stdout. */
+ void dump() const;
+
+ /* Gets instance of ElfFile containing this compilation unit. */
+ ElfFile* elf_file() const {
+ return elf_file_;
+ }
+
+ /* Gets DIE object for this CU. */
+ DIEObject* cu_die() const {
+ return cu_die_;
+ }
+
+ /* Gets byte size of the pointer type for this compilation unit. */
+ Elf_Byte addr_sizeof() const {
+ return addr_sizeof_;
+ }
+
+ /* Gets full path to the compilation directory (DW_AT_comp_dir attribute).
+ * Return:
+ * Full path to the compilation directory (DW_AT_comp_dir attribute),
+ * or NULL, if that attribute was missing in CU's attribute list.
+ */
+ const char* comp_dir_path() const {
+ DIEAttrib attr;
+ return cu_die()->get_attrib(DW_AT_comp_dir, &attr) ? attr.value()->str :
+ NULL;
+ }
+
+ /* Gets relative (from the compilation directory) path to the compiled file.
+ * (DW_AT_name attribute).
+ * Return:
+ * Relative path to the compiled file (DW_AT_name attribute), or NULL, if
+ * that attribute was missing in CU's attribute list.
+ */
+ const char* rel_cu_path() const {
+ DIEAttrib attr;
+ return cu_die()->get_attrib(DW_AT_name, &attr) ? attr.value()->str :
+ NULL;
+ }
+
+ /* Gets next compilation unit in the list. NULL indicates the last CU. */
+ DwarfCU* prev_cu() const {
+ return prev_cu_;
+ }
+
+ /* Links this CU to the list of prevoiusly discovered CUs. */
+ void set_prev_cu(DwarfCU* prev) {
+ prev_cu_ = prev;
+ }
+
+ /* Checks if DWARF version for this CU is higher than 2. */
+ bool is_DWARF3_or_higher() const {
+ return version_ >= 3;
+ }
+
+ /* Gets DIE abbreviation for given abbreviation number.
+ * See DwarfAbbrDieArray::get() */
+ const Dwarf_Abbr_DIE* get_die_abbr(Dwarf_AbbrNum num) const {
+ return abbrs_.get(num);
+ }
+
+ /* Gets DIE object containing given address.
+ * DIE address ranges may overlap (for instance, address range for an inlined
+ * routine will be contained within the address range of a routine where it
+ * was inlined). This method will return a DIE object that is a "leaf" in
+ * that inlining tree. I.e the returned DIE object represents the last DIE
+ * in the branch of all DIEs containing given address.
+ * Param:
+ * address - Address to get a DIE for. NOTE: for the sake of simplicity we
+ * explicitly use 64-bit type for an address.
+ * Return:
+ * Leaf DIE containing given address, or NULL if this CU doesn't contain
+ * the given address.
+ */
+ DIEObject* get_leaf_die_for_address(Elf_Xword address) const {
+ return cu_die_->get_leaf_for_address(address);
+ }
+
+ /* Checks if this CU contains 64, or 32-bit addresses. */
+ bool is_CU_address_64() const {
+ return addr_sizeof_ == 8;
+ }
+ bool is_CU_address_32() const {
+ return addr_sizeof_ == 4;
+ }
+
+//=============================================================================
+// DWARF format dependent methods
+//=============================================================================
+
+ public:
+ /* Parses this compilation unit in .debug_info section, collecting children
+ * DIEs of this compilation unit.
+ * Param:
+ * parse_context - Parsing context that lists tags for DIEs that should be
+ * collected during parsing. NULL passed in this parameter indicates DIEs
+ * for all tags should be collected.
+ * next_cu_die - Upon successful return contains pointer to the next
+ * compilation unit descriptor inside mapped .debug_info section of
+ * the ELF file.
+ * Return:
+ * true on success, false on failure.
+ */
+ virtual bool parse(const DwarfParseContext* parse_context,
+ const void** next_cu_die) = 0;
+
+ /* Gets a DIE object referenced by an offset from the beginning of
+ * this CU in the mapped .debug_info section.
+ */
+ virtual DIEObject* get_referenced_die_object(Elf_Word ref) const = 0;
+
+ /* Gets a reference to a DIE object (offset of the DIE from the
+ * beginning of this CU in the mapped .debug_info section.
+ */
+ virtual Elf_Word get_die_reference(const Dwarf_DIE* die) const = 0;
+
+ /* Gets PC address information.
+ * Param:
+ * address - PC address to get information for.
+ * info - Upon success contains information about routine that belongs to
+ * this compilation unit, containing the given address.
+ * Return:
+ * true on success, or false if this CU doesn't contain the given address.
+ */
+ virtual bool get_pc_address_file_info(Elf_Xword address,
+ Dwarf_AddressInfo* info) = 0;
+
+ /* Gets file descriptor in the mapped .debug_line section of ELF file for a
+ * given index in the file descriptor list.
+ * Param:
+ * index - 1-based index of file descriptor in the file descriptor list.
+ * Return:
+ * File descriptor for the given index, or NULL if index was too big.
+ * NOTE: pointer returned from this method addressed mapped section of
+ * ELF file.
+ */
+ virtual const Dwarf_STMTL_FileDesc* get_stmt_file_info(Elf_Word index) = 0;
+
+ /* Gets directory name by an index in the mapped .debug_line section of
+ * ELF file.
+ * Param:
+ * dir_index - Index of the directory in the file descriptor list. If this
+ * parameter is zero, compilation directory (DW_AT_comp_dir) for this CU
+ * will be returned.
+ * Return:
+ * Directory name for the given index, or NULL if index was too big.
+ * NOTE: pointer returned from this method addressed mapped section of
+ * ELF file.
+ */
+ virtual const char* get_stmt_dir_name(Elf_Word dir_index) = 0;
+
+ protected:
+ /* DIE abbreviation descriptors, cached for this compilation unit. */
+ DwarfAbbrDieArray abbrs_;
+
+ /* Instance of an ELF file that contains this compilation unit. */
+ ElfFile* elf_file_;
+
+ /* DIE object for this CU. */
+ DIEObject* cu_die_;
+
+ /* Next compilation unit in the list (previous in the order they've been
+ * discovered during ELF file parsing).
+ */
+ DwarfCU* prev_cu_;
+
+ /* DWARF version for this CU. */
+ Elf_Half version_;
+
+ /* Byte size of the pointer type for this compilation unit. */
+ Elf_Byte addr_sizeof_;
+};
+
+/* Encapsulates architecture-dependent functionality of a compilation unit.
+ * Template param:
+ * Dwarf_CUHdr - type compilation unit header in the mapped .debug_info
+ * section of ELF file. Must be:
+ * - Dwarf32_CUHdr for 32-bit DWARF, or
+ * - Dwarf64_CUHdr for 64-bit DWARF.
+ * Dwarf_Off - type for an offset field in DWARF data format. Must be:
+ * - Dwarf32_Off for 32-bit DWARF, or
+ * - Dwarf64_Off for 64-bit DWARF.
+ */
+template <typename Dwarf_CUHdr, typename Dwarf_Off>
+class DwarfCUImpl : public DwarfCU {
+ public:
+ /* Constructs DwarfCU instance.
+ * Param:
+ * elf - Instance of ElfFile containing this compilation unit.
+ * hdr - Pointer to compilation unit header inside mapped .debug_info
+ * section of the ELF file.
+ */
+ DwarfCUImpl(ElfFile* elf, const Dwarf_CUHdr* hdr);
+
+ /* Destructs DwarfCU instance. */
+ ~DwarfCUImpl() {
+ }
+
+ /* Parses this compilation unit in .debug_info section, collecting children
+ * DIEs of this compilation unit. This is an implementation of DwarfCU's
+ * abstract metod.
+ * See DwarfCU::parse().
+ */
+ bool parse(const DwarfParseContext* parse_context,
+ const void** next_cu_die);
+
+ /* Gets PC address information.
+ * This is an implementation of DwarfCU's abstract metod.
+ * See DwarfCU::get_pc_address_file_info().
+ */
+ bool get_pc_address_file_info(Elf_Xword address, Dwarf_AddressInfo* info);
+
+ /* Gets file descriptor in the mapped .debug_line section of ELF file for a
+ * given index in the file descriptor list.
+ * This is an implementation of DwarfCU's abstract metod.
+ * See DwarfCU::get_stmt_file_info().
+ */
+ const Dwarf_STMTL_FileDesc* get_stmt_file_info(Elf_Word index);
+
+ /* Gets directory name by an index in the mapped .debug_line section of
+ * ELF file.
+ * This is an implementation of DwarfCU's abstract metod.
+ * See DwarfCU::get_stmt_dir_name().
+ */
+ const char* get_stmt_dir_name(Elf_Word dir_index);
+
+ /* Gets a DIE object referenced by an offset from the beginning of
+ * this CU. This is an implementation of DwarfCU's abstract metod.
+ */
+ DIEObject* get_referenced_die_object(Elf_Word ref) const {
+ const Dwarf_DIE* die = get_referenced_die(ref);
+ return cu_die_->find_die_object(die);
+ }
+
+ /* Gets a reference to a DIE object (offset of the DIE from the
+ * beginning of this CU in the mapped .debug_info section.
+ * This is an implementation of DwarfCU's abstract metod.
+ */
+ Elf_Word get_die_reference(const Dwarf_DIE* die) const {
+ return static_cast<Elf_Word>(diff_ptr(cu_header_, die));
+ }
+
+ protected:
+ /* Process a child DIE (and all its children) in this compilation unit.
+ * Param:
+ * parse_context - See DwarfCU::parse().
+ * die - DIE descriptor of the child to process in this method.
+ * parent_obj - Parent object of the child to process in this method.
+ * NOTE: this parameter can be NULL only for a DIE that represents this
+ * compilation unit itself.
+ * Return:
+ * Pointer to the end of child's attribute list in the mapped .debug_info
+ * section on success, or NULL on failure. Usually, pointer returned from
+ * this method is simply discarded, since parent calculates address of the
+ * next sibling's DIE based on DW_AT_sibling attribute of the DIE preceding
+ * child's DIE.
+ */
+ const Elf_Byte* process_DIE(const DwarfParseContext* parse_context,
+ const Dwarf_DIE* die,
+ DIEObject* parent_obj);
+
+ /* Creates a DIE object for the given DIE.
+ * Param:
+ * parse_context See DwarfCU::parse().
+ * die - DIE to create an object for.
+ * parent - Parent DIE object for the one that's being created in this
+ * method.
+ * tag - Tag of the DIE object that's being created in this method.
+ * Return:
+ * Created DIE object. This method may returns NULL in two cases:
+ * - We're not interested in this DIE (decided by looking at 'tag'
+ * parameter. In this case errno should be set to zero.
+ * - Memory allocation has failed. In this case errno should be
+ * set to ENOMEM.
+ */
+ DIEObject* create_die_object(const DwarfParseContext* parse_context,
+ const Dwarf_DIE* die,
+ DIEObject* parent,
+ Dwarf_Tag tag);
+
+ /* Initializes (caches) STMT lines header for this CU. */
+ bool init_stmtl();
+
+ /* Saves current source file information, collected in the state machine by
+ * the "Line Number Program".
+ * Param:
+ * state - State machine collected "Line Number Program" results.
+ * info - Upon success contains source file information, copied over from
+ * the state machine.
+ * Return:
+ * true on success, or false on failure.
+ */
+ bool set_source_info(const DwarfStateMachine* state,
+ Dwarf_AddressInfo* info);
+
+ /* Gets pointer to the DIE descriptor for this CU. */
+ const Dwarf_DIE* get_DIE() const {
+ /* CU's DIE descriptor immediately follows CU header. */
+ return INC_CPTR_T(Dwarf_DIE, cu_header_, sizeof(Dwarf_CUHdr));
+ }
+
+ /* Caches STMTL header from .debug_line section to stmtl_header_.
+ * Template param:
+ * Dwarf_STMTL_Hdr - Dwarf_STMTL_Hdr32, or Dwarf_STMTL_Hdr64, depending
+ * on the header type.
+ * Param:
+ * stmtl_hdr - STMTL header in the mapped .debug_line section to cache.
+ */
+ template <typename Dwarf_STMTL_Hdr>
+ void cache_stmtl(const Dwarf_STMTL_Hdr* stmtl_hdr) {
+ stmtl_header_.unit_length = elf_file()->pull_val(stmtl_hdr->unit_length.size);
+ stmtl_header_.version = elf_file()->pull_val(stmtl_hdr->version);
+ stmtl_header_.header_length = elf_file()->pull_val(stmtl_hdr->header_length);
+ stmtl_header_.min_instruction_len = stmtl_hdr->min_instruction_len;
+ stmtl_header_.default_is_stmt = stmtl_hdr->default_is_stmt;
+ stmtl_header_.line_base = stmtl_hdr->line_base;
+ stmtl_header_.line_range = stmtl_hdr->line_range;
+ stmtl_header_.opcode_base = stmtl_hdr->opcode_base;
+ stmtl_header_.standard_opcode_lengths = &stmtl_hdr->standard_opcode_lengths;
+ stmtl_header_.start = INC_CPTR_T(Elf_Byte, &stmtl_hdr->min_instruction_len,
+ stmtl_header_.header_length);
+ stmtl_header_.end = INC_CPTR_T(Elf_Byte, &stmtl_hdr->version,
+ stmtl_header_.unit_length);
+ stmtl_header_.include_directories =
+ INC_CPTR_T(char, stmtl_header_.standard_opcode_lengths,
+ stmtl_header_.opcode_base - 1);
+ const char* dir = stmtl_header_.include_directories;
+ while (*dir != '\0') {
+ dir += strlen(dir) + 1;
+ stmtl_header_.inc_dir_num++;
+ }
+ stmtl_header_.file_infos = INC_CPTR_T(Dwarf_STMTL_FileDesc, dir, 1);
+ }
+
+ /* Gets a DIE referenced by an offset from the beginning of this CU
+ * in the mapped .debug_info section.
+ */
+ const Dwarf_DIE* get_referenced_die(Elf_Word ref) const {
+ return INC_CPTR_T(Dwarf_DIE, cu_header_, ref);
+ }
+
+ /* Checks if pointer to the DIE attribute is contained within the CU's area
+ * of the mapped .debug_info section.
+ * Param:
+ * ptr - Pointer to the DIE attribute to check.
+ * Return:
+ * true, if pointer to the DIE attribute is contained within the CU's area
+ * of the mapped .debug_info section, or false if attribute pointer goes
+ * beyond CU's area of the mapped .debug_info section.
+ */
+ bool is_attrib_ptr_valid(const void* ptr) const {
+ return diff_ptr(cu_header_, ptr) < cu_size_;
+ }
+
+ protected:
+ /* Pointer to this compilation unit header inside the mapped .debug_info
+ * section of the ELF file.
+ */
+ const Dwarf_CUHdr* cu_header_;
+
+ /* Size of this compilation unit area in the mapped .debug_info section.
+ * This value has been cached off the CU header in order to avoid
+ * endianness conversions.
+ */
+ Dwarf_Off cu_size_;
+
+ /* STMT lines header, cached off mapped .debug_line section. */
+ Dwarf_STMTL_Hdr stmtl_header_;
+};
+
+#endif // ELFF_DWARF_CU_H_