diff options
author | Chris Johns <chrisj@rtems.org> | 2014-09-13 12:09:16 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2014-09-13 12:09:16 +1000 |
commit | 87e0e76be5b17d1dd27274d58ac9b58cdf71c0ca (patch) | |
tree | 0d44623ad165fa69cd0946f2baab79339b3e6215 /rtemstoolkit/rld-elf.h | |
parent | 749ddf1ed53c3903823eed031649441a59edd264 (diff) |
Refactor code into the RTEMS Toolkit.
Diffstat (limited to 'rtemstoolkit/rld-elf.h')
-rw-r--r-- | rtemstoolkit/rld-elf.h | 756 |
1 files changed, 756 insertions, 0 deletions
diff --git a/rtemstoolkit/rld-elf.h b/rtemstoolkit/rld-elf.h new file mode 100644 index 0000000..fffe036 --- /dev/null +++ b/rtemstoolkit/rld-elf.h @@ -0,0 +1,756 @@ +/* + * Copyright (c) 2011, 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 ELF module manages the libelf interface. + * + */ + +#if !defined (_RLD_ELF_H_) +#define _RLD_ELF_H_ + +#include <list> +#include <map> +#include <vector> + +#include <rld.h> + +namespace rld +{ + namespace elf + { + /** + * Forward decl. + */ + class file; + + /** + * A relocation record. + */ + class relocation + { + public: + /** + * Construct a relocation record. + * + * @param sym The symbol the relocation references. + * @param offset The offset in the section the relocation applies to. + * @param info The relocation info. + * @param addend The constant addend value. + */ + relocation (const symbols::symbol& sym, + elf_addr offset, + elf_xword info, + elf_sxword addend = 0); + + /** + * Default constructor. + */ + relocation (); + + /** + * The offset. + */ + elf_addr offset () const; + + /** + * The type of the relocation record. + */ + uint32_t type () const; + + /** + * The info. + */ + elf_xword info () const; + + /** + * The constant addend. + */ + elf_sxword addend () const; + + /** + * Return the symbol. + */ + const symbols::symbol& symbol () const; + + private: + const symbols::symbol* sym; //< The symbol reference. + elf_addr offset_; //< The offset in the section. + elf_xword info_; //< The record's information. + elf_sxword addend_; //< The constant addend value. + }; + + /** + * A container of relocation records. + */ + typedef std::vector < relocation > relocations; + + /** + * An ELF Section. The current implementation only supports a single data + * descriptor with a section. + */ + class section + { + public: + /** + * Construct the section getting the details from the ELF file given the + * section index. + * + * The section types are (from elf(3)): + * + * Section Type Library Type Description + * ------------ ------------ ----------- + * SHT_DYNAMIC ELF_T_DYN `.dynamic' section entries. + * SHT_DYNSYM ELF_T_SYM Symbols for dynamic linking. + * SHT_FINI_ARRAY ELF_T_ADDR Termination function pointers. + * SHT_GROUP ELF_T_WORD Section group marker. + * SHT_HASH ELF_T_HASH Symbol hashes. + * SHT_INIT_ARRAY ELF_T_ADDR Initialization function pointers. + * SHT_NOBITS ELF_T_BYTE Empty sections. See elf(5). + * SHT_NOTE ELF_T_NOTE ELF note records. + * SHT_PREINIT_ARRAY ELF_T_ADDR Pre-initialization function + * pointers. + * SHT_PROGBITS ELF_T_BYTE Machine code. + * SHT_REL ELF_T_REL ELF relocation records. + * SHT_RELA ELF_T_RELA Relocation records with addends. + * SHT_STRTAB ELF_T_BYTE String tables. + * SHT_SYMTAB ELF_T_SYM Symbol tables. + * SHT_SYMTAB_SHNDX ELF_T_WORD Used with extended section + * numbering. + * SHT_GNU_verdef ELF_T_VDEF Symbol version definitions. + * SHT_GNU_verneed ELF_T_VNEED Symbol versioning requirements. + * SHT_GNU_versym ELF_T_HALF Version symbols. + * SHT_SUNW_move ELF_T_MOVE ELF move records. + * SHT_SUNW_syminfo ELF_T_SYMINFO Additional symbol flags. + * + * @param file_ The ELF file this section is part of. + * @param index_ The section's index. + * @param name The section's name. + * @param type The section's type. + * @param alignment The section's alignment. + * @param flags The section's flags. + * @param addr The section's in-memory address. + * @param offset The section's offset in the file. + * @param size The section's file in bytes. + * @param link The section's header table link. + * @param info The section's extra information. + * @param entry_size The section's entry size. + */ + section (file& file_, + int index_, + const std::string& name, + elf_word type, + elf_xword alignment, + elf_xword flags, + elf_addr addr, + elf_off offset, + elf_xword size, + elf_word link = 0, + elf_word info = 0, + elf_xword entry_size = 0); + + /** + * Construct the section given the details. The ELF file must be + * writable. + * + * @param file_ The ELF file this section is part of. + * @param index The section's index in the ELF file. + */ + section (file& file_, int index); + + /** + * Copy constructor. + */ + section (const section& orig); + + /** + * Default constructor. + */ + section (); + + /** + * Add a data segment descriptor to the section if the file is writable. + * + * These are following data types (from elf(3)): + * + * ELF_T_ADDR Machine addresses. + * ELF_T_BYTE Byte data. The library will not attempt to translate + * byte data. + * ELF_T_CAP Software and hardware capability records. + * ELF_T_DYN Records used in a section of type SHT_DYNAMIC. + * ELF_T_EHDR ELF executable header. + * ELF_T_HALF 16-bit unsigned words. + * ELF_T_LWORD 64 bit unsigned words. + * ELF_T_MOVE ELF Move records. + * ELF_T_NOTE ELF Note structures. + * ELF_T_OFF File offsets. + * ELF_T_PHDR ELF program header table entries. + * ELF_T_REL ELF relocation entries. + * ELF_T_RELA ELF relocation entries with addends. + * ELF_T_SHDR ELF section header entries. + * ELF_T_SWORD Signed 32-bit words. + * ELF_T_SXWORD Signed 64-bit words. + * ELF_T_SYMINFO ELF symbol information. + * ELF_T_SYM ELF symbol table entries. + * ELF_T_VDEF Symbol version definition records. + * ELF_T_VNEED Symbol version requirement records. + * ELF_T_WORD Unsigned 32-bit words. + * ELF_T_XWORD Unsigned 64-bit words. + * + * @param type The type of data in the segment. + * @param alignment The in-file alignment of the data. Must be a power of 2. + * @param size The number of bytes in this data descriptor. + * @param buffer The data in memory. + * @param offset The offset within the containing section. Can be computed. + */ + void add_data (elf_type type, + elf_xword alignment, + elf_xword size, + void* buffer = 0, + elf_off offset = 0); + + /** + * The section's index in the ELF file. + * + * @return int The section number. + */ + int index () const; + + /** + * The name of the section. + * + * @return const std::string& The section's name. + */ + const std::string& name () const; + + /** + * The section's data. + */ + elf_data* data (); + + /** + * Get the type of the section. + */ + elf_word type () const; + + /** + * The section flags. + */ + elf_xword flags () const; + + /** + * In-memory address of the section. + */ + elf_addr address () const; + + /** + * Alignment constraint. + */ + elf_xword alignment () const; + + /** + * The file offset of the section. + */ + elf_off offset () const; + + /** + * The header table link. + */ + elf_word link () const; + + /** + * Extra information. + */ + elf_word info () const; + + /** + * Size of the section. + */ + elf_xword size () const; + + /** + * Size of the entries in the section. + */ + elf_xword entry_size () const; + + /** + * Number of entries. + */ + int entries () const; + + /** + * Return true if the relocation record have an addend field. + * + * @retval true The relocation record have the addend field. + */ + bool get_reloc_type () const; + + /** + * Set the name index if writable. This is normally done + * automatically when adding the section to the file. + */ + void set_name (unsigned int index); + + /** + * Set the type of relocation records. + * + * @param rela If true the records are rela type. + */ + void set_reloc_type (bool rela); + + /** + * Add a relocation. + * + * @param reloc The relocation record to add. + */ + void add (const relocation& reloc); + + /** + * Get the relocations. + */ + const relocations& get_relocations () const; + + private: + + /** + * Check the section is valid. + * + * @param where Where the check is being made. + */ + void check (const char* where) const; + + /** + * Check the section is valid and writable. + * + * @param where Where the check is being made. + */ + void check_writable (const char* where) const; + + file* file_; //< The ELF file. + int index_; //< The section header index. + std::string name_; //< The section's name. + elf_scn* scn; //< ELF private section data. + elf_shdr shdr; //< The section header. + elf_data* data_; //< The section's data. + bool rela; //< The type of relocation records. + relocations relocs; //< The relocation records. + }; + + /** + * Container of ELF section pointers. + */ + typedef std::list < section* > sections; + + /** + * Container of ELF section as a map, ie associative array. + */ + typedef std::map < std::string, section > section_table; + + /** + * An ELF program header. + */ + class program_header + { + public: + /** + * Construct a program header. + */ + program_header (); + + /** + * Desctruct a program header. + */ + ~program_header (); + + /** + * Set the program header. + * + * @param type The type of segment. + * @param flags The segment's flags. + * @param offset The offet to segment. + * @param filesz The segment size in the file. + * @param memsz The segment size in memory. + * @param align The segment alignment. + * @param vaddr The virtual address in memory. + * @param paddr The physical address if any. + */ + void set (elf_word type, + elf_word flags, + elf_off offset, + elf_xword filesz, + elf_xword memsz, + elf_xword align, + elf_addr vaddr, + elf_addr paddr = 0); + + private: + + elf_phdr phdr; //< The ELF program header. + }; + + /** + * A container of program headers. + */ + typedef std::list < program_header > program_headers; + + /** + * An ELF file. + */ + class file + { + public: + /** + * Construct an ELF file. + */ + file (); + + /** + * Destruct the ELF file object. + */ + ~file (); + + /** + * Begin using the ELF file. + * + * @param name The full name of the file. + * @param fd The file descriptor to read or write the file. + * @param writable The file is writeable. The default is false. + */ + void begin (const std::string& name, int fd, const bool writable = false); + + /** + * Begin using the ELF file in an archive. + * + * @param name The full name of the file. + * @param archive The file that is the archive. + * @param offset The offset of the ELF file in the archive. + */ + void begin (const std::string& name, file& archive, off_t offset); + + /** + * End using the ELF file. + */ + void end (); + + /** + * Write the ELF file creating it if it is writable. You should have + * added the sections and the data segment descriptors to the sections + * before calling write. + */ + void write (); + + /** + * Load the header. Done automatically. + */ + void load_header (); + + /** + * Get the machine type. + */ + unsigned int machinetype () const; + + /** + * Get the type of ELF file. + */ + unsigned int type () const; + + /** + * Get the class of the object file. + */ + unsigned int object_class () const; + + /** + * Get the data type, ie LSB or MSB. + */ + unsigned int data_type () const; + + /** + * Is the file an archive format file ? + */ + bool is_archive () const; + + /** + * Is the file an executable ? + */ + bool is_executable () const; + + /** + * Is the file relocatable ? + */ + bool is_relocatable() const; + + /** + * The number of sections in the file. + */ + int section_count () const; + + /** + * Load the sections. + */ + void load_sections (); + + /** + * Get a filtered container of the sections. The key is the section + * type. If the sections are not loaded they are loaded. If the type is 0 + * all sections are returned. + * + * @param filtered_secs The container the copy of the filtered sections + * are placed in. + * @param type The type of sections to filter on. If 0 all sections are + * matched. + */ + void get_sections (sections& filtered_secs, unsigned int type); + + /** + * Return the section with given index. + * + * @param index The section's index to look for. + * @retval section The section matching the index. + */ + section& get_section (int index); + + /** + * Return the index of the string section. + */ + int strings_section () const; + + /** + * Get the string from the specified section at the requested offset. + * + * @param section The section to search for the string. + * @param offset The offset in the string section. + * @return std::string The string. + */ + std::string get_string (int section, size_t offset); + + /** + * Get the string from the ELF header declared string section at the + * requested offset. + * + * @param offset The offset in the string section. + * @return std::string The string. + */ + std::string get_string (size_t offset); + + /** + * Load the symbols. + */ + void load_symbols (); + + /** + * Get a filtered container of symbols given the various types. If the + * symbols are not loaded they are loaded. + * + * @param filtered_syms The filtered symbols found in the file. This is a + * container of pointers. + * @param unresolved Return unresolved symbols. + * @param local Return local symbols. + * @param weak Return weak symbols. + * @param global Return global symbols. + */ + void get_symbols (rld::symbols::pointers& filtered_syms, + bool unresolved = false, + bool local = false, + bool weak = true, + bool global = true); + + /** + * Get the symbol by index in the symtabl section. + */ + const symbols::symbol& get_symbol (const int index) const; + + /** + * Load the relocation records. + */ + void load_relocations (); + + /** + * Clear the relocation records. + */ + void clear_relocations (); + + /** + * Set the ELF header. Must be writable. + * + * The classes are: + * ELFCLASSNONE This class is invalid. + * ELFCLASS32 This defines the 32-bit architecture. It sup- ports + * machines with files and virtual address spa- ces up to + * 4 Gigabytes. + * ELFCLASS64 This defines the 64-bit architecture. + * + * The types are: + * ET_NONE An unknown type. + * ET_REL A relocatable file. + * ET_EXEC An executable file. + * ET_DYN A shared object. + * ET_CORE A core file. + * + * The machine types are: + * TDB + * + * The datatypes are: + * ELFDATA2LSB Two's complement, little-endian. + * ELFDATA2MSB Two's complement, big-endian. + * + * @param type The type of ELF file, ie executable, relocatable etc. + * @param class_ The files ELF class. + * @param machinetype The type of machine code present in the ELF file. + * @param datatype The data type, ie LSB or MSB. + */ + void set_header (elf_half type, + int class_, + elf_half machinetype, + unsigned char datatype); + + /** + * Add a section to the ELF file if writable. + */ + void add (section& sec); + + /** + * Add a program header to the ELF file if writable. + */ + void add (program_header& phdr); + + /** + * Get the ELF reference. + */ + elf* get_elf (); + + /** + * Get the name of the file. + */ + const std::string& name () const; + + /** + * Is the file writable ? + */ + bool is_writable () const; + + private: + + /** + * Begin using the ELF file. + * + * @param name The full name of the file. + * @param fd The file descriptor to read or write the file. + * @param writable The file is writeable. It cannot be part of an archive. + * @param archive The archive's ELF handle or 0 if not an archive. + * @param offset The offset of the ELF file in the archive if elf is non-zero. + */ + void begin (const std::string& name, + int fd, + const bool writable, + file* archive, + off_t offset); + + /** + * Check if the file is usable. Throw an exception if not. + * + * @param where Where the check is performed. + */ + void check (const char* where) const; + + /** + * Check if the file is usable and writable. Throw an exception if not. + * + * @param where Where the check is performed. + */ + void check_writable (const char* where) const; + + /** + * Check if the ELF header is valid. Throw an exception if not. + * + * @param where Where the check is performed. + */ + void check_ehdr (const char* where) const; + + /** + * Check if the ELF program header is valid. Throw an exception if not. + * + * @param where Where the check is performed. + */ + void check_phdr (const char* where) const; + + /** + * Generate libelf error. + * + * @param where Where the error is generated. + */ + void error (const char* where) const; + + int fd_; //< The file handle. + std::string name_; //< The name of the file. + bool archive; //< The ELF file is part of an archive. + bool writable; //< The file is writeable. + elf* elf_; //< The ELF handle. + unsigned int mtype; //< The machine type. + unsigned int oclass; //< The object class. + const char* ident_str; //< The ELF file's ident string. + size_t ident_size; //< The size of the ident. + elf_ehdr* ehdr; //< The ELF header. + elf_phdr* phdr; //< The ELF program header. + section_table secs; //< The sections as a table. + program_headers phdrs; //< The program headers when creating + // ELF files. + rld::symbols::bucket symbols; //< The symbols. All tables point here. + }; + + /** + * Return the machine type label given the machine type. + * + * @param machinetype The ELF machine type. + */ + const std::string machine_type (unsigned int machinetype); + + /** + * Return the global machine type set by the check_file call as a string. + */ + const std::string machine_type (); + + /** + * Return the global class set by the check_file call. + */ + unsigned int object_class (); + + /** + * Return the global machine type set by the check_file call. + */ + unsigned int object_machine_type (); + + /** + * Return the global data type set by the check_file call. + */ + unsigned int object_datatype (); + + /** + * Check the file against the global machine type, object class and data + * type. If this is the first file checked it becomes the default all + * others are checked against. This is a simple way to make sure all files + * are the same type. + * + * @param file The check to check. + */ + void check_file(const file& file); + + } +} + +#endif |