diff options
Diffstat (limited to 'rtemstoolkit/rld-dwarf.h')
-rw-r--r-- | rtemstoolkit/rld-dwarf.h | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/rtemstoolkit/rld-dwarf.h b/rtemstoolkit/rld-dwarf.h new file mode 100644 index 0000000..8a61755 --- /dev/null +++ b/rtemstoolkit/rld-dwarf.h @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2018, Chris Johns <chrisj@rtems.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/** + * @file + * + * @ingroup rtems-ld + * + * @brief RTEMS Linker DWARF module manages the libdwarf interface. + * + */ + +#if !defined (_RLD_DWARF_H_) +#define _RLD_DWARF_H_ + +#include <rld.h> +#include <rld-dwarf-types.h> + +namespace rld +{ + namespace dwarf + { + /** + * Forward decls + */ + class sources; + class debug_info_entry; + class file; + + /** + * Address. + */ + class address + { + public: + address (const sources& source, dwarf_line& line); + address (const address& orig); + address (); + ~address (); + + /** + * Is this address valid? + */ + bool valid () const; + + /** + * The location in the address space. + */ + dwarf_address location () const; + + /** + * Source file path. This is a full path. + */ + std::string path () const; + + /** + * Line number. + */ + int line () const; + + /** + * Is a begin statement? + */ + bool is_a_begin_statement () const; + + /** + * Is in a block? + */ + bool is_in_a_block () const; + + /** + * Is an end sequence? + */ + bool is_an_end_sequence () const; + + /** + * Assigment operator. + */ + address& operator = (address& rhs); + + private: + + dwarf_address addr; + sources const* source; + dwarf_unsigned source_index; + dwarf_unsigned source_line; + bool begin_statement; + bool block; + bool end_sequence; + }; + + /** + * The addresses table is a map of the addresses in a CU to their line + * number. + */ + typedef std::map < const dwarf_address, address > addresses; + + + /** + * Line addresses. + */ + class line_addresses + { + public: + line_addresses (file& debug, debug_info_entry& die); + line_addresses (line_addresses&& orig); + ~line_addresses (); + + /** + * Count of lines. + */ + size_t count () const; + + /** + * Index operator. + */ + dwarf_line& operator [] (const int index); + + private: + + file& debug; + dwarf_line* lines; + dwarf_signed count_; + }; + + /** + * Sources. + * + * This is a CU table of sources. The address's contain an index to a + * string in this table. + */ + class sources + { + public: + sources (file& debug, debug_info_entry& die); + sources (const sources& orig); + sources (sources&& orig); + ~sources (); + + /** + * Index operator. + */ + std::string operator [] (const int index) const; + + /** + * Deallocate. + */ + void dealloc (); + + /** + * Move assignment operator. + */ + sources& operator = (sources&& rhs); + + private: + + file& debug; + char** source; + dwarf_signed count; + dwarf_offset die_offset; + }; + + /** + * Debug Information Element (DIE). + * + * This class clean up and deallocations a DIE when it desctructs. + */ + class debug_info_entry + { + public: + /** + * Construct the DIE, we need to be careful not to share the DIE pointer. + */ + debug_info_entry (file& debug); + debug_info_entry (file& debug, dwarf_die& die); + debug_info_entry (file& debug, dwarf_offset offset); + debug_info_entry (debug_info_entry&& orig); + + /** + * Destruct and clean up. + */ + ~debug_info_entry (); + + /** + * Get the DIE. + */ + dwarf_die get () const; + + /** + * Casting operators to get the DIE. + */ + operator dwarf_die& (); + operator dwarf_die* (); + + /** + * Assignment operators. + */ + debug_info_entry& operator = (debug_info_entry& rhs); + + /** + * Compare operators. + */ + bool operator == (debug_info_entry& rhs) const; + bool operator == (const dwarf_die rhs) const; + + /** + * Get the tag. + */ + dwarf_tag tag (); + + /** + * Get the offset. + */ + dwarf_offset offset (); + + /** + * Get an unsigned attribute. + */ + bool attribute (dwarf_attr attr, + dwarf_unsigned& value, + bool error = true) const; + + /** + * Get a string attribute. + */ + bool attribute (dwarf_attr attr, + std::string& value, + bool error = true) const; + + /** + * Get source lines. Returns the CU line table with all columns. + * + * You need to clean this up. + */ + bool source_lines (dwarf_line*& lines, + dwarf_signed& linecount) const; + + /** + * Get the source files. This is a table of source files in a CU + */ + void source_files (char**& source, + dwarf_signed& sourcecount) const; + + /** + * deallocate the DIE. + */ + void dealloc (); + + private: + + file& debug; + dwarf_die die; + dwarf_tag tag_; + dwarf_offset offset_; + + }; + + /** + * Compilation Unit. + */ + class compilation_unit + { + public: + compilation_unit (file& debug, + debug_info_entry& die, + dwarf_offset offset); + compilation_unit (const compilation_unit& orig); + compilation_unit (compilation_unit&& orig); + ~compilation_unit (); + + /** + * Name of the CU. + */ + std::string name () const; + + /** + * Producer of the CL, the tool that compiled it. + */ + std::string producer () const; + + /** + * The low PC value, 0 if there is no attribute. + */ + unsigned int pc_low () const; + + /** + * The high PC value, ~0 if there is no attribute. + */ + unsigned int pc_high () const; + + /** + * Get the source and line for an address. If the address does not match + * false is returned the file is set to 'unknown' and the line is set to + * 0. + */ + bool get_source (const dwarf_address addr, + address& addr_line); + + /** + * Is the address inside the CU? Becareful using this because not all CUs + * have these attributes set and the address range will be the entire + * address space. + */ + bool inside (dwarf_unsigned addr) const; + + /** + * Move assignment operator. + */ + compilation_unit& operator = (compilation_unit&& rhs); + + /** + * Copy assignment operator. + */ + compilation_unit& operator = (const compilation_unit& rhs); + + private: + + file& debug; ///< The DWARF debug handle. + dwarf_unsigned offset_; ///< The CU offset in .debug_info + std::string name_; ///< The name of the CU. + std::string producer_; ///< The producer of the CU. + dwarf_unsigned pc_low_; ///< The PC low address + dwarf_unsigned pc_high_; ///< The PC high address. + + sources source_; ///< Sources table for this CU. + addresses addr_lines_; ///< Address table. + + dwarf_offset die_offset; ///< The offset of the DIE in the image. + }; + + typedef std::list < compilation_unit > compilation_units; + + /** + * A source and flags. + */ + struct source_flags + { + std::string source; ///< The source file. + rld::strings flags; ///< the flags used to build the code. + + source_flags (const std::string& source); + }; + + typedef std::vector < source_flags > sources_flags; + + /** + * Worker to sort the sources. + */ + struct source_flags_compare + { + const bool by_basename; + + bool operator () (const source_flags& a, const source_flags& b) const; + + source_flags_compare (bool by_basename = true); + }; + + /** + * A container of producers and the source they build. + */ + struct producer_source + { + std::string producer; ///< The producer + sources_flags sources; ///< The sources built by the producer with + /// flags. + + producer_source (const std::string& producer); + producer_source (); + }; + + typedef std::list < producer_source > producer_sources; + + /** + * A DWARF file. + */ + class file + { + public: + /** + * Construct an DWARF file. + */ + file (); + + /** + * Destruct the DWARF file object. + */ + ~file (); + + /** + * Begin using the DWARF information in an ELF file. + * + * @param elf The ELF file. + */ + void begin (rld::elf::file& elf); + + /** + * End using the DWARF file. + */ + void end (); + + /** + * Load the DWARF debug information. + */ + void load_debug (); + + /** + * Get the source location given an address. + */ + bool get_source (const unsigned int address, + std::string& source_file, + int& source_line); + + /** + * Get the producer sources from the compilation units. + */ + void get_producer_sources (producer_sources& producers); + + /** + * Get the DWARF debug information reference. + */ + dwarf& get_debug (); + + /** + * Get the compilation units. + */ + compilation_units& get_cus (); + + /* + * The DWARF debug conversion operator. + */ + operator dwarf () { return get_debug (); } + + /** + * Get the name of the file. + */ + const std::string& name () const; + + private: + + /** + * Check if the file is usable. Throw an exception if not. + * + * @param where Where the check is performed. + */ + void check (const char* where) const; + + dwarf debug; ///< The libdwarf debug data + rld::elf::file* elf_; ///< The libelf reference used to access the + /// DWARF data. + + compilation_units cus; ///< Image's compilation units + }; + + } +} + +#endif |