Add AI generated comments for classes and methods

This commit is contained in:
Serge Lamikhov-Center 2025-01-03 23:40:19 +02:00
parent 4c829d48eb
commit cba0a73823
17 changed files with 1370 additions and 249 deletions

View File

@ -1179,113 +1179,189 @@ constexpr Elf_Word AT_L3_CACHESIZE = 46;
// ELF file header // ELF file header
struct Elf32_Ehdr struct Elf32_Ehdr
{ {
// Identification bytes
unsigned char e_ident[EI_NIDENT]; unsigned char e_ident[EI_NIDENT];
Elf_Half e_type; // Object file type
Elf_Half e_machine; Elf_Half e_type;
Elf_Word e_version; // Architecture
Elf32_Addr e_entry; Elf_Half e_machine;
Elf32_Off e_phoff; // Object file version
Elf32_Off e_shoff; Elf_Word e_version;
Elf_Word e_flags; // Entry point virtual address
Elf_Half e_ehsize; Elf32_Addr e_entry;
Elf_Half e_phentsize; // Program header table file offset
Elf_Half e_phnum; Elf32_Off e_phoff;
Elf_Half e_shentsize; // Section header table file offset
Elf_Half e_shnum; Elf32_Off e_shoff;
Elf_Half e_shstrndx; // Processor-specific flags
Elf_Word e_flags;
// ELF header size in bytes
Elf_Half e_ehsize;
// Program header table entry size
Elf_Half e_phentsize;
// Program header table entry count
Elf_Half e_phnum;
// Section header table entry size
Elf_Half e_shentsize;
// Section header table entry count
Elf_Half e_shnum;
// Section header string table index
Elf_Half e_shstrndx;
}; };
struct Elf64_Ehdr struct Elf64_Ehdr
{ {
// Identification bytes
unsigned char e_ident[EI_NIDENT]; unsigned char e_ident[EI_NIDENT];
Elf_Half e_type; // Object file type
Elf_Half e_machine; Elf_Half e_type;
Elf_Word e_version; // Architecture
Elf64_Addr e_entry; Elf_Half e_machine;
Elf64_Off e_phoff; // Object file version
Elf64_Off e_shoff; Elf_Word e_version;
Elf_Word e_flags; // Entry point virtual address
Elf_Half e_ehsize; Elf64_Addr e_entry;
Elf_Half e_phentsize; // Program header table file offset
Elf_Half e_phnum; Elf64_Off e_phoff;
Elf_Half e_shentsize; // Section header table file offset
Elf_Half e_shnum; Elf64_Off e_shoff;
Elf_Half e_shstrndx; // Processor-specific flags
Elf_Word e_flags;
// ELF header size in bytes
Elf_Half e_ehsize;
// Program header table entry size
Elf_Half e_phentsize;
// Program header table entry count
Elf_Half e_phnum;
// Section header table entry size
Elf_Half e_shentsize;
// Section header table entry count
Elf_Half e_shnum;
// Section header string table index
Elf_Half e_shstrndx;
}; };
// Section header // Section header
struct Elf32_Shdr struct Elf32_Shdr
{ {
Elf_Word sh_name; // Section name (string table index)
Elf_Word sh_type; Elf_Word sh_name;
Elf_Word sh_flags; // Section type
Elf_Word sh_type;
// Section flags
Elf_Word sh_flags;
// Section virtual address at execution
Elf32_Addr sh_addr; Elf32_Addr sh_addr;
Elf32_Off sh_offset; // Section file offset
Elf_Word sh_size; Elf32_Off sh_offset;
Elf_Word sh_link; // Section size in bytes
Elf_Word sh_info; Elf_Word sh_size;
Elf_Word sh_addralign; // Link to another section
Elf_Word sh_entsize; Elf_Word sh_link;
// Additional section information
Elf_Word sh_info;
// Section alignment
Elf_Word sh_addralign;
// Entry size if section holds table
Elf_Word sh_entsize;
}; };
struct Elf64_Shdr struct Elf64_Shdr
{ {
Elf_Word sh_name; // Section name (string table index)
Elf_Word sh_type; Elf_Word sh_name;
Elf_Xword sh_flags; // Section type
Elf_Word sh_type;
// Section flags
Elf_Xword sh_flags;
// Section virtual address at execution
Elf64_Addr sh_addr; Elf64_Addr sh_addr;
Elf64_Off sh_offset; // Section file offset
Elf_Xword sh_size; Elf64_Off sh_offset;
Elf_Word sh_link; // Section size in bytes
Elf_Word sh_info; Elf_Xword sh_size;
Elf_Xword sh_addralign; // Link to another section
Elf_Xword sh_entsize; Elf_Word sh_link;
// Additional section information
Elf_Word sh_info;
// Section alignment
Elf_Xword sh_addralign;
// Entry size if section holds table
Elf_Xword sh_entsize;
}; };
// Segment header // Segment header
struct Elf32_Phdr struct Elf32_Phdr
{ {
Elf_Word p_type; // Segment type
Elf32_Off p_offset; Elf_Word p_type;
// Segment file offset
Elf32_Off p_offset;
// Segment virtual address at execution
Elf32_Addr p_vaddr; Elf32_Addr p_vaddr;
// Segment physical address
Elf32_Addr p_paddr; Elf32_Addr p_paddr;
Elf_Word p_filesz; // Segment size in file
Elf_Word p_memsz; Elf_Word p_filesz;
Elf_Word p_flags; // Segment size in memory
Elf_Word p_align; Elf_Word p_memsz;
// Segment flags
Elf_Word p_flags;
// Segment alignment
Elf_Word p_align;
}; };
struct Elf64_Phdr struct Elf64_Phdr
{ {
Elf_Word p_type; // Segment type
Elf_Word p_flags; Elf_Word p_type;
Elf64_Off p_offset; // Segment flags
Elf_Word p_flags;
// Segment file offset
Elf64_Off p_offset;
// Segment virtual address at execution
Elf64_Addr p_vaddr; Elf64_Addr p_vaddr;
// Segment physical address
Elf64_Addr p_paddr; Elf64_Addr p_paddr;
Elf_Xword p_filesz; // Segment size in file
Elf_Xword p_memsz; Elf_Xword p_filesz;
Elf_Xword p_align; // Segment size in memory
Elf_Xword p_memsz;
// Segment alignment
Elf_Xword p_align;
}; };
// Symbol table entry // Symbol table entry
struct Elf32_Sym struct Elf32_Sym
{ {
Elf_Word st_name; // Symbol name (string table index)
Elf32_Addr st_value; Elf_Word st_name;
Elf_Word st_size; // Symbol value
Elf32_Addr st_value;
// Symbol size
Elf_Word st_size;
// Symbol type and binding attributes
unsigned char st_info; unsigned char st_info;
// Symbol visibility
unsigned char st_other; unsigned char st_other;
Elf_Half st_shndx; // Section index
Elf_Half st_shndx;
}; };
struct Elf64_Sym struct Elf64_Sym
{ {
Elf_Word st_name; // Symbol name (string table index)
Elf_Word st_name;
// Symbol type and binding attributes
unsigned char st_info; unsigned char st_info;
// Symbol visibility
unsigned char st_other; unsigned char st_other;
Elf_Half st_shndx; // Section index
Elf64_Addr st_value; Elf_Half st_shndx;
Elf_Xword st_size; // Symbol value
Elf64_Addr st_value;
// Symbol size
Elf_Xword st_size;
}; };
#define ELF_ST_BIND( i ) ( ( i ) >> 4 ) #define ELF_ST_BIND( i ) ( ( i ) >> 4 )
@ -1297,27 +1373,37 @@ struct Elf64_Sym
// Relocation entries // Relocation entries
struct Elf32_Rel struct Elf32_Rel
{ {
// Location to apply the relocation action
Elf32_Addr r_offset; Elf32_Addr r_offset;
Elf_Word r_info; // Relocation type and symbol index
Elf_Word r_info;
}; };
struct Elf32_Rela struct Elf32_Rela
{ {
// Location to apply the relocation action
Elf32_Addr r_offset; Elf32_Addr r_offset;
Elf_Word r_info; // Relocation type and symbol index
Elf_Sword r_addend; Elf_Word r_info;
// Constant addend used to compute the value
Elf_Sword r_addend;
}; };
struct Elf64_Rel struct Elf64_Rel
{ {
// Location to apply the relocation action
Elf64_Addr r_offset; Elf64_Addr r_offset;
Elf_Xword r_info; // Relocation type and symbol index
Elf_Xword r_info;
}; };
struct Elf64_Rela struct Elf64_Rela
{ {
// Location to apply the relocation action
Elf64_Addr r_offset; Elf64_Addr r_offset;
Elf_Xword r_info; // Relocation type and symbol index
Elf_Xword r_info;
// Constant addend used to compute the value
Elf_Sxword r_addend; Elf_Sxword r_addend;
}; };
@ -1333,54 +1419,79 @@ struct Elf64_Rela
// Dynamic structure // Dynamic structure
struct Elf32_Dyn struct Elf32_Dyn
{ {
// Dynamic entry type
Elf_Sword d_tag; Elf_Sword d_tag;
union { union {
Elf_Word d_val; // Integer value
Elf_Word d_val;
// Address value
Elf32_Addr d_ptr; Elf32_Addr d_ptr;
} d_un; } d_un;
}; };
struct Elf64_Dyn struct Elf64_Dyn
{ {
// Dynamic entry type
Elf_Sxword d_tag; Elf_Sxword d_tag;
union { union {
Elf_Xword d_val; // Integer value
Elf_Xword d_val;
// Address value
Elf64_Addr d_ptr; Elf64_Addr d_ptr;
} d_un; } d_un;
}; };
struct Elfxx_Verdef struct Elfxx_Verdef
{ {
// Version revision
Elf_Half vd_version; Elf_Half vd_version;
// Version information flags
Elf_Half vd_flags; Elf_Half vd_flags;
// Version index
Elf_Half vd_ndx; Elf_Half vd_ndx;
// Number of associated aux entries
Elf_Half vd_cnt; Elf_Half vd_cnt;
// Version name hash value
Elf_Word vd_hash; Elf_Word vd_hash;
// Offset to verdaux array
Elf_Word vd_aux; Elf_Word vd_aux;
// Offset to next verdef entry
Elf_Word vd_next; Elf_Word vd_next;
}; };
struct Elfxx_Verdaux struct Elfxx_Verdaux
{ {
// Version or dependency name
Elf_Word vda_name; Elf_Word vda_name;
// Offset to next verdaux entry
Elf_Word vda_next; Elf_Word vda_next;
}; };
struct Elfxx_Verneed struct Elfxx_Verneed
{ {
// Version of structure
Elf_Half vn_version; Elf_Half vn_version;
// Number of associated aux entries
Elf_Half vn_cnt; Elf_Half vn_cnt;
// Offset to file name string
Elf_Word vn_file; Elf_Word vn_file;
// Offset to vernaux array
Elf_Word vn_aux; Elf_Word vn_aux;
// Offset to next verneed entry
Elf_Word vn_next; Elf_Word vn_next;
}; };
struct Elfxx_Vernaux struct Elfxx_Vernaux
{ {
// Hash value of dependency name
Elf_Word vna_hash; Elf_Word vna_hash;
// Dependency information flags
Elf_Half vna_flags; Elf_Half vna_flags;
// Dependency index
Elf_Half vna_other; Elf_Half vna_other;
// Dependency name string offset
Elf_Word vna_name; Elf_Word vna_name;
// Offset to next vernaux entry
Elf_Word vna_next; Elf_Word vna_next;
}; };
@ -1400,35 +1511,46 @@ struct Elfxx_Vernaux
// The main purpose is also for ELF injectors. // The main purpose is also for ELF injectors.
struct Elf32_auxv struct Elf32_auxv
{ {
// Entry type
uint32_t a_type; // Entry type uint32_t a_type; // Entry type
union { union {
// Integer value, usually a pointer
uint32_t a_val; // Integer value, usually a pointer uint32_t a_val; // Integer value, usually a pointer
} a_un; } a_un;
}; };
struct Elf64_auxv struct Elf64_auxv
{ {
// Entry type
uint64_t a_type; // Entry type uint64_t a_type; // Entry type
union { union {
// Integer value, usually a pointer
uint64_t a_val; // Integer value, usually a pointer uint64_t a_val; // Integer value, usually a pointer
} a_un; } a_un;
}; };
struct Elf32_Chdr struct Elf32_Chdr
{ {
// The compression algorithm used
Elf32_Word ch_type; // The compression algorithm used Elf32_Word ch_type; // The compression algorithm used
// The size, in bytes, of the uncompressed section data
Elf32_Word ch_size; //The size, in bytes, of the uncompressed section data Elf32_Word ch_size; //The size, in bytes, of the uncompressed section data
// The address alignment of the uncompressed section data
Elf32_Word Elf32_Word
ch_addralign; // The address alignment of the uncompressed section data ch_addralign; // The address alignment of the uncompressed section data
}; };
struct Elf64_Chdr struct Elf64_Chdr
{ {
Elf64_Word ch_type; //The compression algorithm used //The compression algorithm used
Elf64_Word ch_type; //The compression algorithm used
// Reserved
Elf64_Word ch_reserved; // Reserved Elf64_Word ch_reserved; // Reserved
Elf_Xword ch_size; //The size, in bytes, of the uncompressed section data //The size, in bytes, of the uncompressed section data
Elf_Xword ch_size; //The size, in bytes, of the uncompressed section data
//The address alignment of the uncompressed section data
Elf_Xword Elf_Xword
ch_addralign; //The address alignment of the uncompressed section data ch_addralign; //The address alignment of the uncompressed section data
}; };

View File

@ -59,15 +59,21 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class elfio
//! \brief The elfio class represents an ELF file and provides methods to manipulate it.
class elfio class elfio
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Default constructor
elfio() noexcept : sections( this ), segments( this ) elfio() noexcept : sections( this ), segments( this )
{ {
create( ELFCLASS32, ELFDATA2LSB ); create( ELFCLASS32, ELFDATA2LSB );
} }
//------------------------------------------------------------------------------
//! \brief Constructor with compression interface
//! \param compression Pointer to the compression interface
explicit elfio( compression_interface* compression ) noexcept explicit elfio( compression_interface* compression ) noexcept
: sections( this ), segments( this ), : sections( this ), segments( this ),
compression( std::shared_ptr<compression_interface>( compression ) ) compression( std::shared_ptr<compression_interface>( compression ) )
@ -75,6 +81,9 @@ class elfio
elfio(); elfio();
} }
//------------------------------------------------------------------------------
//! \brief Move constructor
//! \param other The other elfio object to move from
elfio( elfio&& other ) noexcept elfio( elfio&& other ) noexcept
: sections( this ), segments( this ), : sections( this ), segments( this ),
current_file_pos( other.current_file_pos ) current_file_pos( other.current_file_pos )
@ -92,6 +101,10 @@ class elfio
other.compression = nullptr; other.compression = nullptr;
} }
//------------------------------------------------------------------------------
//! \brief Move assignment operator
//! \param other The other elfio object to move from
//! \return Reference to this object
elfio& operator=( elfio&& other ) noexcept elfio& operator=( elfio&& other ) noexcept
{ {
if ( this != &other ) { if ( this != &other ) {
@ -113,13 +126,15 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// clang-format off //! \brief Delete copy constructor and copy assignment operator
elfio( const elfio& ) = delete; elfio( const elfio& ) = delete;
elfio& operator=( const elfio& ) = delete; elfio& operator=( const elfio& ) = delete;
~elfio() = default; ~elfio() = default;
// clang-format on
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Create a new ELF file with the specified class and encoding
//! \param file_class The class of the ELF file (ELFCLASS32 or ELFCLASS64)
//! \param encoding The encoding of the ELF file (ELFDATA2LSB or ELFDATA2MSB)
void create( unsigned char file_class, unsigned char encoding ) void create( unsigned char file_class, unsigned char encoding )
{ {
sections_.clear(); sections_.clear();
@ -129,12 +144,19 @@ class elfio
create_mandatory_sections(); create_mandatory_sections();
} }
//------------------------------------------------------------------------------
//! \brief Set address translation
//! \param addr_trans Vector of address translations
void set_address_translation( std::vector<address_translation>& addr_trans ) void set_address_translation( std::vector<address_translation>& addr_trans )
{ {
addr_translator.set_address_translation( addr_trans ); addr_translator.set_address_translation( addr_trans );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Load an ELF file from a file
//! \param file_name The name of the file to load
//! \param is_lazy Whether to load the file lazily
//! \return True if successful, false otherwise
bool load( const std::string& file_name, bool is_lazy = false ) bool load( const std::string& file_name, bool is_lazy = false )
{ {
pstream = std::make_unique<std::ifstream>(); pstream = std::make_unique<std::ifstream>();
@ -157,6 +179,10 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Load an ELF file from a stream
//! \param stream The input stream to load from
//! \param is_lazy Whether to load the file lazily
//! \return True if successful, false otherwise
bool load( std::istream& stream, bool is_lazy = false ) bool load( std::istream& stream, bool is_lazy = false )
{ {
sections_.clear(); sections_.clear();
@ -199,6 +225,9 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Save the ELF file to a file
//! \param file_name The name of the file to save to
//! \return True if successful, false otherwise
bool save( const std::string& file_name ) bool save( const std::string& file_name )
{ {
std::ofstream stream; std::ofstream stream;
@ -211,6 +240,9 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Save the ELF file to a stream
//! \param stream The output stream to save to
//! \return True if successful, false otherwise
bool save( std::ostream& stream ) bool save( std::ostream& stream )
{ {
if ( !stream || header == nullptr ) { if ( !stream || header == nullptr ) {
@ -267,9 +299,14 @@ class elfio
ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index ); ELFIO_HEADER_ACCESS_GET_SET( Elf_Half, section_name_str_index );
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the endianness convertor
//! \return Reference to the endianness convertor
const endianness_convertor& get_convertor() const { return convertor; } const endianness_convertor& get_convertor() const { return convertor; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the default entry size for a section type
//! \param section_type The type of the section
//! \return The default entry size for the section type
Elf_Xword get_default_entry_size( Elf_Word section_type ) const Elf_Xword get_default_entry_size( Elf_Word section_type ) const
{ {
switch ( section_type ) { switch ( section_type ) {
@ -307,9 +344,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! returns an empty string if no problems are detected, //! \brief Validate the ELF file
//! or a string containing an error message if problems are found, //! \return An empty string if no problems are detected, or a string containing an error message if problems are found, with one error per line.
//! with one error per line.
std::string validate() const std::string validate() const
{ {
// clang-format off // clang-format off
@ -372,6 +408,10 @@ class elfio
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Check if an offset is within a section
//! \param offset The offset to check
//! \param sec Pointer to the section
//! \return True if the offset is within the section, false otherwise
static bool is_offset_in_section( Elf64_Off offset, const section* sec ) static bool is_offset_in_section( Elf64_Off offset, const section* sec )
{ {
return ( offset >= sec->get_offset() ) && return ( offset >= sec->get_offset() ) &&
@ -379,12 +419,19 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the virtual address of an offset within a section
//! \param offset The offset within the section
//! \param sec Pointer to the section
//! \return The virtual address of the offset within the section
static Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec ) static Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec )
{ {
return sec->get_address() + offset - sec->get_offset(); return sec->get_address() + offset - sec->get_offset();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Find the section that contains a given offset
//! \param offset The offset to find
//! \return Pointer to the section that contains the offset, or nullptr if not found
const section* find_prog_section_for_offset( Elf64_Off offset ) const const section* find_prog_section_for_offset( Elf64_Off offset ) const
{ {
for ( const auto& sec : sections ) { for ( const auto& sec : sections ) {
@ -397,6 +444,10 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Create an ELF header
//! \param file_class The class of the ELF file (ELFCLASS32 or ELFCLASS64)
//! \param encoding The encoding of the ELF file (ELFDATA2LSB or ELFDATA2MSB)
//! \return Unique pointer to the created ELF header
std::unique_ptr<elf_header> create_header( unsigned char file_class, std::unique_ptr<elf_header> create_header( unsigned char file_class,
unsigned char encoding ) unsigned char encoding )
{ {
@ -420,6 +471,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Create a new section
//! \return Pointer to the created section
section* create_section() section* create_section()
{ {
if ( auto file_class = get_class(); file_class == ELFCLASS64 ) { if ( auto file_class = get_class(); file_class == ELFCLASS64 ) {
@ -444,6 +497,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Create a new segment
//! \return Pointer to the created segment
segment* create_segment() segment* create_segment()
{ {
if ( auto file_class = header->get_class(); file_class == ELFCLASS64 ) { if ( auto file_class = header->get_class(); file_class == ELFCLASS64 ) {
@ -468,6 +523,7 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Create mandatory sections
void create_mandatory_sections() void create_mandatory_sections()
{ {
// Create null section without calling to 'add_section' as no string // Create null section without calling to 'add_section' as no string
@ -484,6 +540,10 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Load sections from a stream
//! \param stream The input stream to load from
//! \param is_lazy Whether to load the sections lazily
//! \return True if successful, false otherwise
bool load_sections( std::istream& stream, bool is_lazy ) bool load_sections( std::istream& stream, bool is_lazy )
{ {
unsigned char file_class = header->get_class(); unsigned char file_class = header->get_class();
@ -525,9 +585,14 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! Checks whether the addresses of the section entirely fall within the given segment. //! \brief Checks whether the addresses of the section entirely fall within the given segment.
//! It doesn't matter if the addresses are memory addresses, or file offsets, //! It doesn't matter if the addresses are memory addresses, or file offsets,
//! they just need to be in the same address space //! they just need to be in the same address space
//! \param sect_begin The beginning address of the section
//! \param sect_size The size of the section
//! \param seg_begin The beginning address of the segment
//! \param seg_end The end address of the segment
//! \return True if the section is within the segment, false otherwise
static bool is_sect_in_seg( Elf64_Off sect_begin, static bool is_sect_in_seg( Elf64_Off sect_begin,
Elf_Xword sect_size, Elf_Xword sect_size,
Elf64_Off seg_begin, Elf64_Off seg_begin,
@ -542,6 +607,10 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Load segments from a stream
//! \param stream The input stream to load from
//! \param is_lazy Whether to load the segments lazily
//! \return True if successful, false otherwise
bool load_segments( std::istream& stream, bool is_lazy ) bool load_segments( std::istream& stream, bool is_lazy )
{ {
unsigned char file_class = header->get_class(); unsigned char file_class = header->get_class();
@ -618,12 +687,18 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Save the ELF header to a stream
//! \param stream The output stream to save to
//! \return True if successful, false otherwise
bool save_header( std::ostream& stream ) const bool save_header( std::ostream& stream ) const
{ {
return header->save( stream ); return header->save( stream );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Save the sections to a stream
//! \param stream The output stream to save to
//! \return True if successful, false otherwise
bool save_sections( std::ostream& stream ) const bool save_sections( std::ostream& stream ) const
{ {
for ( const auto& sec : sections_ ) { for ( const auto& sec : sections_ ) {
@ -639,6 +714,9 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Save the segments to a stream
//! \param stream The output stream to save to
//! \return True if successful, false otherwise
bool save_segments( std::ostream& stream ) const bool save_segments( std::ostream& stream ) const
{ {
for ( const auto& seg : segments_ ) { for ( const auto& seg : segments_ ) {
@ -654,6 +732,9 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Check if a section is without a segment
//! \param section_index The index of the section
//! \return True if the section is without a segment, false otherwise
bool is_section_without_segment( unsigned int section_index ) const bool is_section_without_segment( unsigned int section_index ) const
{ {
bool found = false; bool found = false;
@ -669,6 +750,10 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Check if a segment is a subsequence of another segment
//! \param seg1 Pointer to the first segment
//! \param seg2 Pointer to the second segment
//! \return True if seg1 is a subsequence of seg2, false otherwise
static bool is_subsequence_of( const segment* seg1, const segment* seg2 ) static bool is_subsequence_of( const segment* seg1, const segment* seg2 )
{ {
// Return 'true' if sections of seg1 are a subset of sections in seg2 // Return 'true' if sections of seg1 are a subset of sections in seg2
@ -685,6 +770,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get ordered segments
//! \return Vector of ordered segments
std::vector<segment*> get_ordered_segments() const std::vector<segment*> get_ordered_segments() const
{ {
std::vector<segment*> res; std::vector<segment*> res;
@ -731,6 +818,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Layout sections without segments
//! \return True if successful, false otherwise
bool layout_sections_without_segments() bool layout_sections_without_segments()
{ {
for ( unsigned int i = 0; i < sections_.size(); ++i ) { for ( unsigned int i = 0; i < sections_.size(); ++i ) {
@ -759,6 +848,7 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Calculate segment alignment
void calc_segment_alignment() const void calc_segment_alignment() const
{ {
for ( const auto& seg : segments_ ) { for ( const auto& seg : segments_ ) {
@ -772,6 +862,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Layout segments and their sections
//! \return True if successful, false otherwise
bool layout_segments_and_their_sections() bool layout_segments_and_their_sections()
{ {
std::vector<segment*> worklist; std::vector<segment*> worklist;
@ -841,6 +933,8 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Layout the section table
//! \return True if successful, false otherwise
bool layout_section_table() bool layout_section_table()
{ {
// Simply place the section table at the end for now // Simply place the section table at the end for now
@ -851,6 +945,13 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Write segment data
//! \param seg Pointer to the segment
//! \param section_generated Vector of section generated flags
//! \param segment_memory Reference to the segment memory size
//! \param segment_filesize Reference to the segment file size
//! \param seg_start_pos The start position of the segment
//! \return True if successful, false otherwise
bool write_segment_data( const segment* seg, bool write_segment_data( const segment* seg,
std::vector<bool>& section_generated, std::vector<bool>& section_generated,
Elf_Xword& segment_memory, Elf_Xword& segment_memory,
@ -944,20 +1045,29 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
public: public:
//! \class Sections
//! \brief The Sections class provides methods to manipulate sections in an ELF file.
friend class Sections; friend class Sections;
class Sections class Sections
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param parent Pointer to the parent elfio object
explicit Sections( elfio* parent ) : parent( parent ) {} explicit Sections( elfio* parent ) : parent( parent ) {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of sections
//! \return The number of sections
Elf_Half size() const Elf_Half size() const
{ {
return static_cast<Elf_Half>( parent->sections_.size() ); return static_cast<Elf_Half>( parent->sections_.size() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a section by index
//! \param index The index of the section
//! \return Pointer to the section, or nullptr if not found
section* operator[]( unsigned int index ) const section* operator[]( unsigned int index ) const
{ {
section* sec = nullptr; section* sec = nullptr;
@ -970,6 +1080,9 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a section by name
//! \param name The name of the section
//! \return Pointer to the section, or nullptr if not found
section* operator[]( const std::string_view& name ) const section* operator[]( const std::string_view& name ) const
{ {
section* sec = nullptr; section* sec = nullptr;
@ -985,6 +1098,9 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a new section
//! \param name The name of the section
//! \return Pointer to the created section
section* add( const std::string& name ) const section* add( const std::string& name ) const
{ {
section* new_section = parent->create_section(); section* new_section = parent->create_section();
@ -1000,24 +1116,32 @@ class elfio
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an iterator to the beginning of the sections
//! \return Iterator to the beginning of the sections
std::vector<std::unique_ptr<section>>::iterator begin() std::vector<std::unique_ptr<section>>::iterator begin()
{ {
return parent->sections_.begin(); return parent->sections_.begin();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an iterator to the end of the sections
//! \return Iterator to the end of the sections
std::vector<std::unique_ptr<section>>::iterator end() std::vector<std::unique_ptr<section>>::iterator end()
{ {
return parent->sections_.end(); return parent->sections_.end();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a const iterator to the beginning of the sections
//! \return Const iterator to the beginning of the sections
std::vector<std::unique_ptr<section>>::const_iterator begin() const std::vector<std::unique_ptr<section>>::const_iterator begin() const
{ {
return parent->sections_.cbegin(); return parent->sections_.cbegin();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a const iterator to the end of the sections
//! \return Const iterator to the end of the sections
std::vector<std::unique_ptr<section>>::const_iterator end() const std::vector<std::unique_ptr<section>>::const_iterator end() const
{ {
return parent->sections_.cend(); return parent->sections_.cend();
@ -1025,52 +1149,71 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
elfio* parent; elfio* parent; //!< Pointer to the parent elfio object
}; };
Sections sections; Sections sections; //!< Sections object
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class Segments
//! \brief The Segments class provides methods to manipulate segments in an ELF file.
friend class Segments; friend class Segments;
class Segments class Segments
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param parent Pointer to the parent elfio object
explicit Segments( elfio* parent ) : parent( parent ) {} explicit Segments( elfio* parent ) : parent( parent ) {}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of segments
//! \return The number of segments
Elf_Half size() const Elf_Half size() const
{ {
return static_cast<Elf_Half>( parent->segments_.size() ); return static_cast<Elf_Half>( parent->segments_.size() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a segment by index
//! \param index The index of the segment
//! \return Pointer to the segment, or nullptr if not found
segment* operator[]( unsigned int index ) const segment* operator[]( unsigned int index ) const
{ {
return parent->segments_[index].get(); return parent->segments_[index].get();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a new segment
//! \return Pointer to the created segment
segment* add() { return parent->create_segment(); } segment* add() { return parent->create_segment(); }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an iterator to the beginning of the segments
//! \return Iterator to the beginning of the segments
std::vector<std::unique_ptr<segment>>::iterator begin() std::vector<std::unique_ptr<segment>>::iterator begin()
{ {
return parent->segments_.begin(); return parent->segments_.begin();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an iterator to the end of the segments
//! \return Iterator to the end of the segments
std::vector<std::unique_ptr<segment>>::iterator end() std::vector<std::unique_ptr<segment>>::iterator end()
{ {
return parent->segments_.end(); return parent->segments_.end();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a const iterator to the beginning of the segments
//! \return Const iterator to the beginning of the segments
std::vector<std::unique_ptr<segment>>::const_iterator begin() const std::vector<std::unique_ptr<segment>>::const_iterator begin() const
{ {
return parent->segments_.cbegin(); return parent->segments_.cbegin();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a const iterator to the end of the segments
//! \return Const iterator to the end of the segments
std::vector<std::unique_ptr<segment>>::const_iterator end() const std::vector<std::unique_ptr<segment>>::const_iterator end() const
{ {
return parent->segments_.cend(); return parent->segments_.cend();
@ -1078,21 +1221,23 @@ class elfio
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
elfio* parent; elfio* parent; //!< Pointer to the parent elfio object
}; };
Segments segments; Segments segments; //!< Segments object
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
std::unique_ptr<std::ifstream> pstream = nullptr; std::unique_ptr<std::ifstream> pstream =
std::unique_ptr<elf_header> header = nullptr; nullptr; //!< Pointer to the input stream
std::vector<std::unique_ptr<section>> sections_; std::unique_ptr<elf_header> header = nullptr; //!< Pointer to the ELF header
std::vector<std::unique_ptr<segment>> segments_; std::vector<std::unique_ptr<section>> sections_; //!< Vector of sections
endianness_convertor convertor; std::vector<std::unique_ptr<segment>> segments_; //!< Vector of segments
address_translator addr_translator; endianness_convertor convertor; //!< Endianness convertor
std::shared_ptr<compression_interface> compression = nullptr; address_translator addr_translator; //!< Address translator
std::shared_ptr<compression_interface> compression =
nullptr; //!< Pointer to the compression interface
Elf_Xword current_file_pos = 0; Elf_Xword current_file_pos = 0; //!< Current file position
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -28,55 +28,86 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Template class for accessing array sections
template <class S, typename T> class array_section_accessor_template template <class S, typename T> class array_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Constructor
explicit array_section_accessor_template( const elfio& elf_file, explicit array_section_accessor_template( const elfio& elf_file,
S* section ) S* section );
: elf_file( elf_file ), array_section( section )
{
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Xword get_entries_num() const // Returns the number of entries in the array section
{ Elf_Xword get_entries_num() const;
Elf_Xword entry_size = sizeof( T );
return array_section->get_size() / entry_size;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool get_entry( Elf_Xword index, Elf64_Addr& address ) const // Retrieves an entry from the array section
{ bool get_entry( Elf_Xword index, Elf64_Addr& address ) const;
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
const endianness_convertor& convertor = elf_file.get_convertor();
const T temp = *reinterpret_cast<const T*>( array_section->get_data() +
index * sizeof( T ) );
address = convertor( temp );
return true;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void add_entry( Elf64_Addr address ) // Adds an entry to the array section
{ void add_entry( Elf64_Addr address );
const endianness_convertor& convertor = elf_file.get_convertor();
T temp = convertor( (T)address );
array_section->append_data( reinterpret_cast<char*>( &temp ),
sizeof( temp ) );
}
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Reference to the ELF file
const elfio& elf_file; const elfio& elf_file;
S* array_section; //------------------------------------------------------------------------------
// Pointer to the array section
S* array_section;
}; };
//------------------------------------------------------------------------------
// Constructor
template <class S, typename T>
array_section_accessor_template<S, T>::array_section_accessor_template(
const elfio& elf_file, S* section )
: elf_file( elf_file ), array_section( section )
{
}
//------------------------------------------------------------------------------
// Returns the number of entries in the array section
template <class S, typename T>
Elf_Xword array_section_accessor_template<S, T>::get_entries_num() const
{
Elf_Xword entry_size = sizeof( T );
return array_section->get_size() / entry_size;
}
//------------------------------------------------------------------------------
// Retrieves an entry from the array section
template <class S, typename T>
bool array_section_accessor_template<S, T>::get_entry(
Elf_Xword index, Elf64_Addr& address ) const
{
if ( index >= get_entries_num() ) { // Is index valid
return false;
}
const endianness_convertor& convertor = elf_file.get_convertor();
const T temp = *reinterpret_cast<const T*>( array_section->get_data() +
index * sizeof( T ) );
address = convertor( temp );
return true;
}
//------------------------------------------------------------------------------
// Adds an entry to the array section
template <class S, typename T>
void array_section_accessor_template<S, T>::add_entry( Elf64_Addr address )
{
const endianness_convertor& convertor = elf_file.get_convertor();
T temp = convertor( (T)address );
array_section->append_data( reinterpret_cast<char*>( &temp ),
sizeof( temp ) );
}
// Type aliases for array section accessors
template <typename T = Elf32_Word> template <typename T = Elf32_Word>
using array_section_accessor = array_section_accessor_template<section, T>; using array_section_accessor = array_section_accessor_template<section, T>;
template <typename T = Elf32_Word> template <typename T = Elf32_Word>

View File

@ -672,6 +672,7 @@ static const struct note_tag_t
static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64; static const ELFIO::Elf_Xword MAX_DATA_ENTRIES = 64;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Class representing the ELF dump functionality
class dump class dump
{ {
#define DUMP_DEC_FORMAT( width ) \ #define DUMP_DEC_FORMAT( width ) \
@ -685,6 +686,7 @@ class dump
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the ELF header information
static void header( std::ostream& out, const elfio& reader ) static void header( std::ostream& out, const elfio& reader )
{ {
if ( !reader.get_header_size() ) { if ( !reader.get_header_size() ) {
@ -713,6 +715,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the section headers information
static void section_headers( std::ostream& out, const elfio& reader ) static void section_headers( std::ostream& out, const elfio& reader )
{ {
Elf_Half n = reader.sections.size(); Elf_Half n = reader.sections.size();
@ -748,6 +751,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps a single section header information
static void section_header( std::ostream& out, static void section_header( std::ostream& out,
Elf_Half no, Elf_Half no,
const section* sec, const section* sec,
@ -792,6 +796,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the segment headers information
static void segment_headers( std::ostream& out, const elfio& reader ) static void segment_headers( std::ostream& out, const elfio& reader )
{ {
Elf_Half n = reader.segments.size(); Elf_Half n = reader.segments.size();
@ -836,6 +841,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps a single segment header information
static void segment_header( std::ostream& out, static void segment_header( std::ostream& out,
Elf_Half no, Elf_Half no,
const segment* seg, const segment* seg,
@ -874,6 +880,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the symbol tables information
static void symbol_tables( std::ostream& out, const elfio& reader ) static void symbol_tables( std::ostream& out, const elfio& reader )
{ {
for ( const auto& sec : reader.sections ) { // For all sections for ( const auto& sec : reader.sections ) { // For all sections
@ -918,6 +925,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps a single symbol table entry information
static void symbol_table( std::ostream& out, static void symbol_table( std::ostream& out,
Elf_Xword no, Elf_Xword no,
const std::string& name, const std::string& name,
@ -954,6 +962,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the notes information
static void notes( std::ostream& out, const elfio& reader ) static void notes( std::ostream& out, const elfio& reader )
{ {
for ( const auto& sec : reader.sections ) { // For all sections for ( const auto& sec : reader.sections ) { // For all sections
@ -1018,6 +1027,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps a single note information
static void note( std::ostream& out, static void note( std::ostream& out,
int no, int no,
Elf_Word type, Elf_Word type,
@ -1065,6 +1075,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the module information
static void modinfo( std::ostream& out, const elfio& reader ) static void modinfo( std::ostream& out, const elfio& reader )
{ {
for ( const auto& sec : reader.sections ) { // For all sections for ( const auto& sec : reader.sections ) { // For all sections
@ -1088,6 +1099,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the dynamic tags information
static void dynamic_tags( std::ostream& out, const elfio& reader ) static void dynamic_tags( std::ostream& out, const elfio& reader )
{ {
for ( const auto& sec : reader.sections ) { // For all sections for ( const auto& sec : reader.sections ) { // For all sections
@ -1118,6 +1130,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps a single dynamic tag information
static void dynamic_tag( std::ostream& out, static void dynamic_tag( std::ostream& out,
Elf_Xword no, Elf_Xword no,
Elf_Xword tag, Elf_Xword tag,
@ -1137,6 +1150,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the section data
static void section_data( std::ostream& out, const section* sec ) static void section_data( std::ostream& out, const section* sec )
{ {
std::ios_base::fmtflags original_flags = out.flags(); std::ios_base::fmtflags original_flags = out.flags();
@ -1169,6 +1183,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps all sections data
static void section_datas( std::ostream& out, const elfio& reader ) static void section_datas( std::ostream& out, const elfio& reader )
{ {
Elf_Half n = reader.sections.size(); Elf_Half n = reader.sections.size();
@ -1191,6 +1206,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps the segment data
static void static void
segment_data( std::ostream& out, Elf_Half no, const segment* seg ) segment_data( std::ostream& out, Elf_Half no, const segment* seg )
{ {
@ -1224,6 +1240,7 @@ class dump
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Dumps all segments data
static void segment_datas( std::ostream& out, const elfio& reader ) static void segment_datas( std::ostream& out, const elfio& reader )
{ {
Elf_Half n = reader.segments.size(); Elf_Half n = reader.segments.size();

View File

@ -28,10 +28,12 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Template class for accessing dynamic sections
template <class S> class dynamic_section_accessor_template template <class S> class dynamic_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Constructor
explicit dynamic_section_accessor_template( const elfio& elf_file, explicit dynamic_section_accessor_template( const elfio& elf_file,
S* section ) S* section )
: elf_file( elf_file ), dynamic_section( section ), entries_num( 0 ) : elf_file( elf_file ), dynamic_section( section ), entries_num( 0 )
@ -39,6 +41,7 @@ template <class S> class dynamic_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns the number of entries in the dynamic section
Elf_Xword get_entries_num() const Elf_Xword get_entries_num() const
{ {
size_t needed_entry_size = -1; size_t needed_entry_size = -1;
@ -70,6 +73,7 @@ template <class S> class dynamic_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Retrieves an entry from the dynamic section
bool get_entry( Elf_Xword index, bool get_entry( Elf_Xword index,
Elf_Xword& tag, Elf_Xword& tag,
Elf_Xword& value, Elf_Xword& value,
@ -106,6 +110,7 @@ template <class S> class dynamic_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Adds an entry to the dynamic section
void add_entry( Elf_Xword tag, Elf_Xword value ) void add_entry( Elf_Xword tag, Elf_Xword value )
{ {
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
@ -117,6 +122,7 @@ template <class S> class dynamic_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Adds an entry with a string value to the dynamic section
void add_entry( Elf_Xword tag, const std::string& str ) void add_entry( Elf_Xword tag, const std::string& str )
{ {
string_section_accessor strsec( string_section_accessor strsec(
@ -125,15 +131,16 @@ template <class S> class dynamic_section_accessor_template
add_entry( tag, value ); add_entry( tag, value );
} }
//------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Returns the index of the string table
Elf_Half get_string_table_index() const Elf_Half get_string_table_index() const
{ {
return (Elf_Half)dynamic_section->get_link(); return (Elf_Half)dynamic_section->get_link();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Retrieves a generic entry from the dynamic section
template <class T> template <class T>
void generic_get_entry_dyn( Elf_Xword index, void generic_get_entry_dyn( Elf_Xword index,
Elf_Xword& tag, Elf_Xword& tag,
@ -200,6 +207,7 @@ template <class S> class dynamic_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Adds a generic entry to the dynamic section
template <class T> template <class T>
void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value ) void generic_add_entry_dyn( Elf_Xword tag, Elf_Xword value )
{ {
@ -258,13 +266,16 @@ template <class S> class dynamic_section_accessor_template
sizeof( entry ) ); sizeof( entry ) );
} }
//------------------------------------------------------------------------------
private: private:
const elfio& elf_file; // Reference to the ELF file
S* dynamic_section; const elfio& elf_file;
// Pointer to the dynamic section
S* dynamic_section;
// Number of entries in the dynamic section
mutable Elf_Xword entries_num; mutable Elf_Xword entries_num;
}; };
// Type aliases for dynamic section accessors
using dynamic_section_accessor = dynamic_section_accessor_template<section>; using dynamic_section_accessor = dynamic_section_accessor_template<section>;
using const_dynamic_section_accessor = using const_dynamic_section_accessor =
dynamic_section_accessor_template<const section>; dynamic_section_accessor_template<const section>;

View File

@ -27,12 +27,30 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
/**
* @class elf_header
* @brief Abstract base class for ELF header.
*/
class elf_header class elf_header
{ {
public: public:
/**
* @brief Virtual destructor.
*/
virtual ~elf_header() = default; virtual ~elf_header() = default;
virtual bool load( std::istream& stream ) = 0; /**
* @brief Load ELF header from stream.
* @param stream Input stream.
* @return True if successful, false otherwise.
*/
virtual bool load( std::istream& stream ) = 0;
/**
* @brief Save ELF header to stream.
* @param stream Output stream.
* @return True if successful, false otherwise.
*/
virtual bool save( std::ostream& stream ) const = 0; virtual bool save( std::ostream& stream ) const = 0;
// ELF header functions // ELF header functions
@ -57,6 +75,10 @@ class elf_header
ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index ); ELFIO_GET_SET_ACCESS_DECL( Elf_Half, section_name_str_index );
}; };
/**
* @struct elf_header_impl_types
* @brief Template specialization for ELF header implementation types.
*/
template <class T> struct elf_header_impl_types; template <class T> struct elf_header_impl_types;
template <> struct elf_header_impl_types<Elf32_Ehdr> template <> struct elf_header_impl_types<Elf32_Ehdr>
{ {
@ -71,10 +93,19 @@ template <> struct elf_header_impl_types<Elf64_Ehdr>
static const unsigned char file_class = ELFCLASS64; static const unsigned char file_class = ELFCLASS64;
}; };
/**
* @class elf_header_impl
* @brief Template class for ELF header implementation.
*/
template <class T> class elf_header_impl : public elf_header template <class T> class elf_header_impl : public elf_header
{ {
public: public:
//------------------------------------------------------------------------------ /**
* @brief Constructor.
* @param convertor Endianness convertor.
* @param encoding Encoding type.
* @param translator Address translator.
*/
elf_header_impl( endianness_convertor* convertor, elf_header_impl( endianness_convertor* convertor,
unsigned char encoding, unsigned char encoding,
const address_translator* translator ) const address_translator* translator )
@ -99,7 +130,11 @@ template <class T> class elf_header_impl : public elf_header
header.e_shentsize = ( *convertor )( header.e_shentsize ); header.e_shentsize = ( *convertor )( header.e_shentsize );
} }
//------------------------------------------------------------------------------ /**
* @brief Load ELF header from stream.
* @param stream Input stream.
* @return True if successful, false otherwise.
*/
bool load( std::istream& stream ) override bool load( std::istream& stream ) override
{ {
stream.seekg( ( *translator )[0] ); stream.seekg( ( *translator )[0] );
@ -108,7 +143,11 @@ template <class T> class elf_header_impl : public elf_header
return ( stream.gcount() == sizeof( header ) ); return ( stream.gcount() == sizeof( header ) );
} }
//------------------------------------------------------------------------------ /**
* @brief Save ELF header to stream.
* @param stream Output stream.
* @return True if successful, false otherwise.
*/
bool save( std::ostream& stream ) const override bool save( std::ostream& stream ) const override
{ {
stream.seekp( ( *translator )[0] ); stream.seekp( ( *translator )[0] );

View File

@ -29,10 +29,21 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* @class modinfo_section_accessor_template
* @brief A template class to access modinfo section.
*
* @tparam S The section type.
*/
template <class S> class modinfo_section_accessor_template template <class S> class modinfo_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* @brief Construct a new modinfo section accessor template object.
*
* @param section The section to be accessed.
*/
explicit modinfo_section_accessor_template( S* section ) explicit modinfo_section_accessor_template( S* section )
: modinfo_section( section ) : modinfo_section( section )
{ {
@ -40,9 +51,23 @@ template <class S> class modinfo_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* @brief Get the number of attributes.
*
* @return Elf_Word The number of attributes.
*/
Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); } Elf_Word get_attribute_num() const { return (Elf_Word)content.size(); }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* @brief Get the attribute by index.
*
* @param no The index of the attribute.
* @param field The field name of the attribute.
* @param value The value of the attribute.
* @return true If the attribute is found.
* @return false If the attribute is not found.
*/
bool bool
get_attribute( Elf_Word no, std::string& field, std::string& value ) const get_attribute( Elf_Word no, std::string& field, std::string& value ) const
{ {
@ -56,6 +81,14 @@ template <class S> class modinfo_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* @brief Get the attribute by field name.
*
* @param field_name The field name of the attribute.
* @param value The value of the attribute.
* @return true If the attribute is found.
* @return false If the attribute is not found.
*/
bool get_attribute( const std::string_view& field_name, bool get_attribute( const std::string_view& field_name,
std::string& value ) const std::string& value ) const
{ {
@ -70,6 +103,13 @@ template <class S> class modinfo_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/**
* @brief Add a new attribute.
*
* @param field The field name of the attribute.
* @param value The value of the attribute.
* @return Elf_Word The position of the new attribute.
*/
Elf_Word add_attribute( const std::string& field, const std::string& value ) Elf_Word add_attribute( const std::string& field, const std::string& value )
{ {
Elf_Word current_position = 0; Elf_Word current_position = 0;
@ -89,6 +129,9 @@ template <class S> class modinfo_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
/**
* @brief Process the section to extract attributes.
*/
void process_section() void process_section()
{ {
const char* pdata = modinfo_section->get_data(); const char* pdata = modinfo_section->get_data();
@ -111,8 +154,9 @@ template <class S> class modinfo_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
S* modinfo_section; S* modinfo_section; ///< The section to be accessed.
std::vector<std::pair<std::string, std::string>> content; std::vector<std::pair<std::string, std::string>>
content; ///< The list of attributes.
}; };
using modinfo_section_accessor = modinfo_section_accessor_template<section>; using modinfo_section_accessor = modinfo_section_accessor_template<section>;

View File

@ -38,11 +38,16 @@ namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class note_section_accessor_template
//! \brief Class for accessing note section data
template <class S, Elf_Xword ( S::*F_get_size )() const> template <class S, Elf_Xword ( S::*F_get_size )() const>
class note_section_accessor_template class note_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param elf_file Reference to the ELF file
//! \param section Pointer to the section
explicit note_section_accessor_template( const elfio& elf_file, S* section ) explicit note_section_accessor_template( const elfio& elf_file, S* section )
: elf_file( elf_file ), notes( section ) : elf_file( elf_file ), notes( section )
{ {
@ -50,12 +55,21 @@ class note_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of notes
//! \return Number of notes
Elf_Word get_notes_num() const Elf_Word get_notes_num() const
{ {
return (Elf_Word)note_start_positions.size(); return (Elf_Word)note_start_positions.size();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a note
//! \param index Index of the note
//! \param type Type of the note
//! \param name Name of the note
//! \param desc Pointer to the descriptor
//! \param descSize Size of the descriptor
//! \return True if successful, false otherwise
bool get_note( Elf_Word index, bool get_note( Elf_Word index,
Elf_Word& type, Elf_Word& type,
std::string& name, std::string& name,
@ -94,6 +108,11 @@ class note_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a note
//! \param type Type of the note
//! \param name Name of the note
//! \param desc Pointer to the descriptor
//! \param descSize Size of the descriptor
void add_note( Elf_Word type, void add_note( Elf_Word type,
const std::string& name, const std::string& name,
const char* desc, const char* desc,
@ -129,6 +148,7 @@ class note_section_accessor_template
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Process the section to extract note start positions
void process_section() void process_section()
{ {
const endianness_convertor& convertor = elf_file.get_convertor(); const endianness_convertor& convertor = elf_file.get_convertor();
@ -165,9 +185,10 @@ class note_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file; //!< Reference to the ELF file
S* notes; S* notes; //!< Pointer to the section or segment
std::vector<Elf_Xword> note_start_positions; std::vector<Elf_Xword>
note_start_positions; //!< Vector of note start positions
}; };
using note_section_accessor = using note_section_accessor =

View File

@ -28,10 +28,18 @@ namespace ELFIO {
template <typename T> struct get_sym_and_type; template <typename T> struct get_sym_and_type;
template <> struct get_sym_and_type<Elf32_Rel> template <> struct get_sym_and_type<Elf32_Rel>
{ {
//------------------------------------------------------------------------------
//! \brief Get the symbol from the relocation info
//! \param info Relocation info
//! \return Symbol
static int get_r_sym( Elf_Xword info ) static int get_r_sym( Elf_Xword info )
{ {
return ELF32_R_SYM( (Elf_Word)info ); return ELF32_R_SYM( (Elf_Word)info );
} }
//------------------------------------------------------------------------------
//! \brief Get the type from the relocation info
//! \param info Relocation info
//! \return Type
static int get_r_type( Elf_Xword info ) static int get_r_type( Elf_Xword info )
{ {
return ELF32_R_TYPE( (Elf_Word)info ); return ELF32_R_TYPE( (Elf_Word)info );
@ -39,10 +47,18 @@ template <> struct get_sym_and_type<Elf32_Rel>
}; };
template <> struct get_sym_and_type<Elf32_Rela> template <> struct get_sym_and_type<Elf32_Rela>
{ {
//------------------------------------------------------------------------------
//! \brief Get the symbol from the relocation info
//! \param info Relocation info
//! \return Symbol
static int get_r_sym( Elf_Xword info ) static int get_r_sym( Elf_Xword info )
{ {
return ELF32_R_SYM( (Elf_Word)info ); return ELF32_R_SYM( (Elf_Word)info );
} }
//------------------------------------------------------------------------------
//! \brief Get the type from the relocation info
//! \param info Relocation info
//! \return Type
static int get_r_type( Elf_Xword info ) static int get_r_type( Elf_Xword info )
{ {
return ELF32_R_TYPE( (Elf_Word)info ); return ELF32_R_TYPE( (Elf_Word)info );
@ -50,20 +66,41 @@ template <> struct get_sym_and_type<Elf32_Rela>
}; };
template <> struct get_sym_and_type<Elf64_Rel> template <> struct get_sym_and_type<Elf64_Rel>
{ {
//------------------------------------------------------------------------------
//! \brief Get the symbol from the relocation info
//! \param info Relocation info
//! \return Symbol
static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
//------------------------------------------------------------------------------
//! \brief Get the type from the relocation info
//! \param info Relocation info
//! \return Type
static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
}; };
template <> struct get_sym_and_type<Elf64_Rela> template <> struct get_sym_and_type<Elf64_Rela>
{ {
//------------------------------------------------------------------------------
//! \brief Get the symbol from the relocation info
//! \param info Relocation info
//! \return Symbol
static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); } static int get_r_sym( Elf_Xword info ) { return ELF64_R_SYM( info ); }
//------------------------------------------------------------------------------
//! \brief Get the type from the relocation info
//! \param info Relocation info
//! \return Type
static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); } static int get_r_type( Elf_Xword info ) { return ELF64_R_TYPE( info ); }
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class relocation_section_accessor_template
//! \brief Class for accessing relocation section data
template <class S> class relocation_section_accessor_template template <class S> class relocation_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param elf_file Reference to the ELF file
//! \param section Pointer to the section
explicit relocation_section_accessor_template( const elfio& elf_file, explicit relocation_section_accessor_template( const elfio& elf_file,
S* section ) S* section )
: elf_file( elf_file ), relocation_section( section ) : elf_file( elf_file ), relocation_section( section )
@ -71,6 +108,8 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of entries
//! \return Number of entries
Elf_Xword get_entries_num() const Elf_Xword get_entries_num() const
{ {
Elf_Xword nRet = 0; Elf_Xword nRet = 0;
@ -84,6 +123,13 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an entry
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
//! \return True if successful, false otherwise
bool get_entry( Elf_Xword index, bool get_entry( Elf_Xword index,
Elf64_Addr& offset, Elf64_Addr& offset,
Elf_Word& symbol, Elf_Word& symbol,
@ -119,6 +165,15 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an entry with additional information
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbolValue Value of the symbol
//! \param symbolName Name of the symbol
//! \param type Type of the entry
//! \param addend Addend of the entry
//! \param calcValue Calculated value
//! \return True if successful, false otherwise
bool get_entry( Elf_Xword index, bool get_entry( Elf_Xword index,
Elf64_Addr& offset, Elf64_Addr& offset,
Elf64_Addr& symbolValue, Elf64_Addr& symbolValue,
@ -186,6 +241,13 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set an entry
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
//! \return True if successful, false otherwise
bool set_entry( Elf_Xword index, bool set_entry( Elf_Xword index,
Elf64_Addr offset, Elf64_Addr offset,
Elf_Word symbol, Elf_Word symbol,
@ -221,6 +283,9 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add an entry
//! \param offset Offset of the entry
//! \param info Information of the entry
void add_entry( Elf64_Addr offset, Elf_Xword info ) void add_entry( Elf64_Addr offset, Elf_Xword info )
{ {
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
@ -232,6 +297,10 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add an entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type ) void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned type )
{ {
Elf_Xword info; Elf_Xword info;
@ -246,6 +315,10 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add an entry
//! \param offset Offset of the entry
//! \param info Information of the entry
//! \param addend Addend of the entry
void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) void add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )
{ {
if ( elf_file.get_class() == ELFCLASS32 ) { if ( elf_file.get_class() == ELFCLASS32 ) {
@ -257,6 +330,11 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add an entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
void add_entry( Elf64_Addr offset, void add_entry( Elf64_Addr offset,
Elf_Word symbol, Elf_Word symbol,
unsigned type, unsigned type,
@ -274,6 +352,17 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add an entry with additional information
//! \param str_writer String section accessor
//! \param str String
//! \param sym_writer Symbol section accessor
//! \param value Value of the symbol
//! \param size Size of the symbol
//! \param sym_info Symbol information
//! \param other Other information
//! \param shndx Section index
//! \param offset Offset of the entry
//! \param type Type of the entry
void add_entry( string_section_accessor str_writer, void add_entry( string_section_accessor str_writer,
const char* str, const char* str,
symbol_section_accessor sym_writer, symbol_section_accessor sym_writer,
@ -292,6 +381,9 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Swap symbols
//! \param first First symbol
//! \param second Second symbol
void swap_symbols( Elf_Xword first, Elf_Xword second ) void swap_symbols( Elf_Xword first, Elf_Xword second )
{ {
Elf64_Addr offset = 0; Elf64_Addr offset = 0;
@ -312,12 +404,21 @@ template <class S> class relocation_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the symbol table index
//! \return Symbol table index
Elf_Half get_symbol_table_index() const Elf_Half get_symbol_table_index() const
{ {
return (Elf_Half)relocation_section->get_link(); return (Elf_Half)relocation_section->get_link();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a generic entry for REL type
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
//! \return True if successful, false otherwise
template <class T> template <class T>
bool generic_get_entry_rel( Elf_Xword index, bool generic_get_entry_rel( Elf_Xword index,
Elf64_Addr& offset, Elf64_Addr& offset,
@ -342,6 +443,13 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a generic entry for RELA type
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
//! \return True if successful, false otherwise
template <class T> template <class T>
bool generic_get_entry_rela( Elf_Xword index, bool generic_get_entry_rela( Elf_Xword index,
Elf64_Addr& offset, Elf64_Addr& offset,
@ -367,6 +475,12 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set a generic entry for REL type
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
template <class T> template <class T>
void generic_set_entry_rel( Elf_Xword index, void generic_set_entry_rel( Elf_Xword index,
Elf64_Addr offset, Elf64_Addr offset,
@ -392,6 +506,12 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set a generic entry for RELA type
//! \param index Index of the entry
//! \param offset Offset of the entry
//! \param symbol Symbol of the entry
//! \param type Type of the entry
//! \param addend Addend of the entry
template <class T> template <class T>
void generic_set_entry_rela( Elf_Xword index, void generic_set_entry_rela( Elf_Xword index,
Elf64_Addr offset, Elf64_Addr offset,
@ -419,6 +539,9 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a generic entry for REL type
//! \param offset Offset of the entry
//! \param info Information of the entry
template <class T> template <class T>
void generic_add_entry( Elf64_Addr offset, Elf_Xword info ) void generic_add_entry( Elf64_Addr offset, Elf_Xword info )
{ {
@ -435,6 +558,10 @@ template <class S> class relocation_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a generic entry for RELA type
//! \param offset Offset of the entry
//! \param info Information of the entry
//! \param addend Addend of the entry
template <class T> template <class T>
void void
generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend ) generic_add_entry( Elf64_Addr offset, Elf_Xword info, Elf_Sxword addend )

View File

@ -30,6 +30,10 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
/**
* @class section
* @brief Represents a section in an ELF file.
*/
class section class section
{ {
friend class elfio; friend class elfio;
@ -50,35 +54,117 @@ class section
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset );
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
virtual const char* get_data() const = 0; /**
virtual void free_data() const = 0; * @brief Get the data of the section.
virtual void set_data( const char* raw_data, Elf_Word size ) = 0; * @return Pointer to the data.
virtual void set_data( const std::string& data ) = 0; */
virtual void append_data( const char* raw_data, Elf_Word size ) = 0; virtual const char* get_data() const = 0;
virtual void append_data( const std::string& data ) = 0;
/**
* @brief Free the data of the section.
*/
virtual void free_data() const = 0;
/**
* @brief Set the data of the section.
* @param raw_data Pointer to the raw data.
* @param size Size of the data.
*/
virtual void set_data( const char* raw_data, Elf_Word size ) = 0;
/**
* @brief Set the data of the section.
* @param data String containing the data.
*/
virtual void set_data( const std::string& data ) = 0;
/**
* @brief Append data to the section.
* @param raw_data Pointer to the raw data.
* @param size Size of the data.
*/
virtual void append_data( const char* raw_data, Elf_Word size ) = 0;
/**
* @brief Append data to the section.
* @param data String containing the data.
*/
virtual void append_data( const std::string& data ) = 0;
/**
* @brief Insert data into the section at a specific position.
* @param pos Position to insert the data.
* @param raw_data Pointer to the raw data.
* @param size Size of the data.
*/
virtual void virtual void
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0; insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) = 0;
virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0;
virtual size_t get_stream_size() const = 0; /**
virtual void set_stream_size( size_t value ) = 0; * @brief Insert data into the section at a specific position.
* @param pos Position to insert the data.
* @param data String containing the data.
*/
virtual void insert_data( Elf_Xword pos, const std::string& data ) = 0;
/**
* @brief Get the size of the stream.
* @return Size of the stream.
*/
virtual size_t get_stream_size() const = 0;
/**
* @brief Set the size of the stream.
* @param value Size of the stream.
*/
virtual void set_stream_size( size_t value ) = 0;
protected: protected:
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index ); ELFIO_SET_ACCESS_DECL( Elf_Half, index );
/**
* @brief Load the section from a stream.
* @param stream Input stream.
* @param header_offset Offset of the header.
* @param is_lazy Whether to load lazily.
* @return True if successful, false otherwise.
*/
virtual bool load( std::istream& stream, virtual bool load( std::istream& stream,
std::streampos header_offset, std::streampos header_offset,
bool is_lazy ) = 0; bool is_lazy ) = 0;
/**
* @brief Save the section to a stream.
* @param stream Output stream.
* @param header_offset Offset of the header.
* @param data_offset Offset of the data.
*/
virtual void save( std::ostream& stream, virtual void save( std::ostream& stream,
std::streampos header_offset, std::streampos header_offset,
std::streampos data_offset ) = 0; std::streampos data_offset ) = 0;
virtual bool is_address_initialized() const = 0;
/**
* @brief Check if the address is initialized.
* @return True if initialized, false otherwise.
*/
virtual bool is_address_initialized() const = 0;
}; };
/**
* @class section_impl
* @brief Implementation of the section class.
* @tparam T Type of the section header.
*/
template <class T> class section_impl : public section template <class T> class section_impl : public section
{ {
public: public:
//------------------------------------------------------------------------------ /**
* @brief Constructor.
* @param convertor Pointer to the endianness convertor.
* @param translator Pointer to the address translator.
* @param compression Shared pointer to the compression interface.
*/
section_impl( const endianness_convertor* convertor, section_impl( const endianness_convertor* convertor,
const address_translator* translator, const address_translator* translator,
const std::shared_ptr<compression_interface>& compression ) const std::shared_ptr<compression_interface>& compression )
@ -87,7 +173,6 @@ template <class T> class section_impl : public section
{ {
} }
//------------------------------------------------------------------------------
// Section info functions // Section info functions
ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type );
ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags ); ELFIO_GET_SET_ACCESS( Elf_Xword, flags, header.sh_flags );
@ -98,19 +183,32 @@ template <class T> class section_impl : public section
ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize ); ELFIO_GET_SET_ACCESS( Elf_Xword, entry_size, header.sh_entsize );
ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name ); ELFIO_GET_SET_ACCESS( Elf_Word, name_string_offset, header.sh_name );
ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr ); ELFIO_GET_ACCESS( Elf64_Addr, address, header.sh_addr );
//------------------------------------------------------------------------------
/**
* @brief Get the index of the section.
* @return Index of the section.
*/
Elf_Half get_index() const override { return index; } Elf_Half get_index() const override { return index; }
//------------------------------------------------------------------------------ /**
* @brief Get the name of the section.
* @return Name of the section.
*/
std::string get_name() const override { return name; } std::string get_name() const override { return name; }
//------------------------------------------------------------------------------ /**
* @brief Set the name of the section.
* @param name_prm Name of the section.
*/
void set_name( const std::string& name_prm ) override void set_name( const std::string& name_prm ) override
{ {
this->name = name_prm; this->name = name_prm;
} }
//------------------------------------------------------------------------------ /**
* @brief Set the address of the section.
* @param value Address of the section.
*/
void set_address( const Elf64_Addr& value ) override void set_address( const Elf64_Addr& value ) override
{ {
header.sh_addr = decltype( header.sh_addr )( value ); header.sh_addr = decltype( header.sh_addr )( value );
@ -118,10 +216,16 @@ template <class T> class section_impl : public section
is_address_set = true; is_address_set = true;
} }
//------------------------------------------------------------------------------ /**
* @brief Check if the address is initialized.
* @return True if initialized, false otherwise.
*/
bool is_address_initialized() const override { return is_address_set; } bool is_address_initialized() const override { return is_address_set; }
//------------------------------------------------------------------------------ /**
* @brief Get the data of the section.
* @return Pointer to the data.
*/
const char* get_data() const override const char* get_data() const override
{ {
if ( !is_loaded ) { if ( !is_loaded ) {
@ -130,7 +234,9 @@ template <class T> class section_impl : public section
return data.get(); return data.get();
} }
//------------------------------------------------------------------------------ /**
* @brief Free the data of the section.
*/
void free_data() const override void free_data() const override
{ {
if ( is_lazy ) { if ( is_lazy ) {
@ -139,7 +245,11 @@ template <class T> class section_impl : public section
} }
} }
//------------------------------------------------------------------------------ /**
* @brief Set the data of the section.
* @param raw_data Pointer to the raw data.
* @param size Size of the data.
*/
void set_data( const char* raw_data, Elf_Word size ) override void set_data( const char* raw_data, Elf_Word size ) override
{ {
if ( get_type() != SHT_NOBITS ) { if ( get_type() != SHT_NOBITS ) {
@ -159,25 +269,40 @@ template <class T> class section_impl : public section
} }
} }
//------------------------------------------------------------------------------ /**
* @brief Set the data of the section.
* @param str_data String containing the data.
*/
void set_data( const std::string& str_data ) override void set_data( const std::string& str_data ) override
{ {
return set_data( str_data.c_str(), (Elf_Word)str_data.size() ); return set_data( str_data.c_str(), (Elf_Word)str_data.size() );
} }
//------------------------------------------------------------------------------ /**
* @brief Append data to the section.
* @param raw_data Pointer to the raw data.
* @param size Size of the data.
*/
void append_data( const char* raw_data, Elf_Word size ) override void append_data( const char* raw_data, Elf_Word size ) override
{ {
insert_data( get_size(), raw_data, size ); insert_data( get_size(), raw_data, size );
} }
//------------------------------------------------------------------------------ /**
* @brief Append data to the section.
* @param str_data String containing the data.
*/
void append_data( const std::string& str_data ) override void append_data( const std::string& str_data ) override
{ {
return append_data( str_data.c_str(), (Elf_Word)str_data.size() ); return append_data( str_data.c_str(), (Elf_Word)str_data.size() );
} }
//------------------------------------------------------------------------------ /**
* @brief Insert data into the section at a specific position.
* @param pos Position to insert the data.
* @param raw_data Pointer to the raw data.
* @param size Size of the data.
*/
void void
insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override insert_data( Elf_Xword pos, const char* raw_data, Elf_Word size ) override
{ {
@ -213,25 +338,41 @@ template <class T> class section_impl : public section
} }
} }
//------------------------------------------------------------------------------ /**
* @brief Insert data into the section at a specific position.
* @param pos Position to insert the data.
* @param str_data String containing the data.
*/
void insert_data( Elf_Xword pos, const std::string& str_data ) override void insert_data( Elf_Xword pos, const std::string& str_data ) override
{ {
return insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() ); return insert_data( pos, str_data.c_str(), (Elf_Word)str_data.size() );
} }
/**
* @brief Get the size of the stream.
* @return Size of the stream.
*/
size_t get_stream_size() const override { return stream_size; } size_t get_stream_size() const override { return stream_size; }
//------------------------------------------------------------------------------ /**
* @brief Set the size of the stream.
* @param value Size of the stream.
*/
void set_stream_size( size_t value ) override { stream_size = value; } void set_stream_size( size_t value ) override { stream_size = value; }
//------------------------------------------------------------------------------
protected: protected:
//------------------------------------------------------------------------------
ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset ); ELFIO_GET_SET_ACCESS( Elf64_Off, offset, header.sh_offset );
//------------------------------------------------------------------------------ /**
* @brief Set the index of the section.
* @param value Index of the section.
*/
void set_index( const Elf_Half& value ) override { index = value; } void set_index( const Elf_Half& value ) override { index = value; }
/**
* @brief Check if the section is compressed.
* @return True if compressed, false otherwise.
*/
bool is_compressed() const bool is_compressed() const
{ {
return ( ( get_flags() & SHF_RPX_DEFLATE ) || return ( ( get_flags() & SHF_RPX_DEFLATE ) ||
@ -239,7 +380,13 @@ template <class T> class section_impl : public section
compression != nullptr; compression != nullptr;
} }
//------------------------------------------------------------------------------ /**
* @brief Load the section from a stream.
* @param stream Input stream.
* @param header_offset Offset of the header.
* @param is_lazy_ Whether to load lazily.
* @return True if successful, false otherwise.
*/
bool load( std::istream& stream, bool load( std::istream& stream,
std::streampos header_offset, std::streampos header_offset,
bool is_lazy_ ) override bool is_lazy_ ) override
@ -278,6 +425,10 @@ template <class T> class section_impl : public section
return true; return true;
} }
/**
* @brief Load the data of the section.
* @return True if successful, false otherwise.
*/
bool load_data() const bool load_data() const
{ {
Elf_Xword sh_offset = Elf_Xword sh_offset =
@ -312,7 +463,12 @@ template <class T> class section_impl : public section
return true; return true;
} }
//------------------------------------------------------------------------------ /**
* @brief Save the section to a stream.
* @param stream Output stream.
* @param header_offset Offset of the header.
* @param data_offset Offset of the data.
*/
void save( std::ostream& stream, void save( std::ostream& stream,
std::streampos header_offset, std::streampos header_offset,
std::streampos data_offset ) override std::streampos data_offset ) override
@ -329,9 +485,12 @@ template <class T> class section_impl : public section
} }
} }
//------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ /**
* @brief Save the header of the section to a stream.
* @param stream Output stream.
* @param header_offset Offset of the header.
*/
void save_header( std::ostream& stream, std::streampos header_offset ) const void save_header( std::ostream& stream, std::streampos header_offset ) const
{ {
adjust_stream_size( stream, header_offset ); adjust_stream_size( stream, header_offset );
@ -339,7 +498,11 @@ template <class T> class section_impl : public section
sizeof( header ) ); sizeof( header ) );
} }
//------------------------------------------------------------------------------ /**
* @brief Save the data of the section to a stream.
* @param stream Output stream.
* @param data_offset Offset of the data.
*/
void save_data( std::ostream& stream, std::streampos data_offset ) void save_data( std::ostream& stream, std::streampos data_offset )
{ {
adjust_stream_size( stream, data_offset ); adjust_stream_size( stream, data_offset );
@ -358,21 +521,26 @@ template <class T> class section_impl : public section
} }
} }
//------------------------------------------------------------------------------
private: private:
mutable std::istream* pstream = nullptr; mutable std::istream* pstream =
T header = {}; nullptr; /**< Pointer to the input stream. */
Elf_Half index = 0; T header = {}; /**< Section header. */
std::string name; Elf_Half index = 0; /**< Index of the section. */
mutable std::unique_ptr<char[]> data; std::string name; /**< Name of the section. */
mutable Elf_Word data_size = 0; mutable std::unique_ptr<char[]> data; /**< Pointer to the data. */
const endianness_convertor* convertor = nullptr; mutable Elf_Word data_size = 0; /**< Size of the data. */
const address_translator* translator = nullptr; const endianness_convertor* convertor =
const std::shared_ptr<compression_interface> compression = nullptr; nullptr; /**< Pointer to the endianness convertor. */
bool is_address_set = false; const address_translator* translator =
size_t stream_size = 0; nullptr; /**< Pointer to the address translator. */
mutable bool is_lazy = false; const std::shared_ptr<compression_interface> compression =
mutable bool is_loaded = false; nullptr; /**< Shared pointer to the compression interface. */
bool is_address_set = false; /**< Flag indicating if the address is set. */
size_t stream_size = 0; /**< Size of the stream. */
mutable bool is_lazy =
false; /**< Flag indicating if lazy loading is enabled. */
mutable bool is_loaded =
false; /**< Flag indicating if the data is loaded. */
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -30,6 +30,9 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------
//! \class segment
//! \brief Class for accessing segment data
class segment class segment
{ {
friend class elfio; friend class elfio;
@ -37,45 +40,122 @@ class segment
public: public:
virtual ~segment() = default; virtual ~segment() = default;
//------------------------------------------------------------------------------
//! \brief Get the index of the segment
//! \return Index of the segment
ELFIO_GET_ACCESS_DECL( Elf_Half, index ); ELFIO_GET_ACCESS_DECL( Elf_Half, index );
//------------------------------------------------------------------------------
//! \brief Get the type of the segment
//! \return Type of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, type );
//------------------------------------------------------------------------------
//! \brief Get the flags of the segment
//! \return Flags of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags ); ELFIO_GET_SET_ACCESS_DECL( Elf_Word, flags );
//------------------------------------------------------------------------------
//! \brief Get the alignment of the segment
//! \return Alignment of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, align );
//------------------------------------------------------------------------------
//! \brief Get the virtual address of the segment
//! \return Virtual address of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, virtual_address );
//------------------------------------------------------------------------------
//! \brief Get the physical address of the segment
//! \return Physical address of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address ); ELFIO_GET_SET_ACCESS_DECL( Elf64_Addr, physical_address );
//------------------------------------------------------------------------------
//! \brief Get the file size of the segment
//! \return File size of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, file_size );
//------------------------------------------------------------------------------
//! \brief Get the memory size of the segment
//! \return Memory size of the segment
ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size ); ELFIO_GET_SET_ACCESS_DECL( Elf_Xword, memory_size );
//------------------------------------------------------------------------------
//! \brief Get the offset of the segment
//! \return Offset of the segment
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
virtual const char* get_data() const = 0; //------------------------------------------------------------------------------
virtual void free_data() const = 0; //! \brief Get the data of the segment
//! \return Pointer to the data
virtual const char* get_data() const = 0;
//------------------------------------------------------------------------------
//! \brief Free the data of the segment
virtual void free_data() const = 0;
//------------------------------------------------------------------------------
//! \brief Add a section to the segment
//! \param psec Pointer to the section
//! \param addr_align Alignment of the section
//! \return Index of the added section
virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0; virtual Elf_Half add_section( section* psec, Elf_Xword addr_align ) = 0;
//------------------------------------------------------------------------------
//! \brief Add a section index to the segment
//! \param index Index of the section
//! \param addr_align Alignment of the section
//! \return Index of the added section
virtual Elf_Half add_section_index( Elf_Half index, virtual Elf_Half add_section_index( Elf_Half index,
Elf_Xword addr_align ) = 0; Elf_Xword addr_align ) = 0;
virtual Elf_Half get_sections_num() const = 0; //------------------------------------------------------------------------------
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0; //! \brief Get the number of sections in the segment
virtual bool is_offset_initialized() const = 0; //! \return Number of sections in the segment
virtual Elf_Half get_sections_num() const = 0;
//------------------------------------------------------------------------------
//! \brief Get the index of a section at a given position
//! \param num Position of the section
//! \return Index of the section
virtual Elf_Half get_section_index_at( Elf_Half num ) const = 0;
//------------------------------------------------------------------------------
//! \brief Check if the offset is initialized
//! \return True if the offset is initialized, false otherwise
virtual bool is_offset_initialized() const = 0;
protected: protected:
//------------------------------------------------------------------------------
//! \brief Set the offset of the segment
//! \param offset Offset of the segment
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
//------------------------------------------------------------------------------
//! \brief Set the index of the segment
//! \param index Index of the segment
ELFIO_SET_ACCESS_DECL( Elf_Half, index ); ELFIO_SET_ACCESS_DECL( Elf_Half, index );
//------------------------------------------------------------------------------
//! \brief Get the sections of the segment
//! \return Vector of section indices
virtual const std::vector<Elf_Half>& get_sections() const = 0; virtual const std::vector<Elf_Half>& get_sections() const = 0;
//------------------------------------------------------------------------------
//! \brief Load the segment from a stream
//! \param stream Input stream
//! \param header_offset Offset of the segment header
//! \param is_lazy Whether to load the segment lazily
//! \return True if successful, false otherwise
virtual bool load( std::istream& stream, virtual bool load( std::istream& stream,
std::streampos header_offset, std::streampos header_offset,
bool is_lazy ) = 0; bool is_lazy ) = 0;
//------------------------------------------------------------------------------
//! \brief Save the segment to a stream
//! \param stream Output stream
//! \param header_offset Offset of the segment header
//! \param data_offset Offset of the segment data
virtual void save( std::ostream& stream, virtual void save( std::ostream& stream,
std::streampos header_offset, std::streampos header_offset,
std::streampos data_offset ) = 0; std::streampos data_offset ) = 0;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class segment_impl
//! \brief Implementation of the segment class
template <class T> class segment_impl : public segment template <class T> class segment_impl : public segment
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param convertor Pointer to the endianness convertor
//! \param translator Pointer to the address translator
segment_impl( const endianness_convertor* convertor, segment_impl( const endianness_convertor* convertor,
const address_translator* translator ) const address_translator* translator )
: convertor( convertor ), translator( translator ) : convertor( convertor ), translator( translator )
@ -94,9 +174,13 @@ template <class T> class segment_impl : public segment
ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset ); ELFIO_GET_ACCESS( Elf64_Off, offset, ph.p_offset );
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the index of the segment
//! \return Index of the segment
Elf_Half get_index() const override { return index; } Elf_Half get_index() const override { return index; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the data of the segment
//! \return Pointer to the data
const char* get_data() const override const char* get_data() const override
{ {
if ( !is_loaded ) { if ( !is_loaded ) {
@ -106,6 +190,7 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Free the data of the segment
void free_data() const override void free_data() const override
{ {
if ( is_lazy ) { if ( is_lazy ) {
@ -115,6 +200,10 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a section index to the segment
//! \param sec_index Index of the section
//! \param addr_align Alignment of the section
//! \return Index of the added section
Elf_Half add_section_index( Elf_Half sec_index, Elf_Half add_section_index( Elf_Half sec_index,
Elf_Xword addr_align ) override Elf_Xword addr_align ) override
{ {
@ -127,18 +216,27 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a section to the segment
//! \param psec Pointer to the section
//! \param addr_align Alignment of the section
//! \return Index of the added section
Elf_Half add_section( section* psec, Elf_Xword addr_align ) override Elf_Half add_section( section* psec, Elf_Xword addr_align ) override
{ {
return add_section_index( psec->get_index(), addr_align ); return add_section_index( psec->get_index(), addr_align );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of sections in the segment
//! \return Number of sections in the segment
Elf_Half get_sections_num() const override Elf_Half get_sections_num() const override
{ {
return (Elf_Half)sections.size(); return (Elf_Half)sections.size();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the index of a section at a given position
//! \param num Position of the section
//! \return Index of the section
Elf_Half get_section_index_at( Elf_Half num ) const override Elf_Half get_section_index_at( Elf_Half num ) const override
{ {
if ( num < sections.size() ) { if ( num < sections.size() ) {
@ -151,8 +249,8 @@ template <class T> class segment_impl : public segment
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
protected: protected:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set the offset of the segment
//------------------------------------------------------------------------------ //! \param value Offset of the segment
void set_offset( const Elf64_Off& value ) override void set_offset( const Elf64_Off& value ) override
{ {
ph.p_offset = decltype( ph.p_offset )( value ); ph.p_offset = decltype( ph.p_offset )( value );
@ -161,18 +259,29 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Check if the offset is initialized
//! \return True if the offset is initialized, false otherwise
bool is_offset_initialized() const override { return is_offset_set; } bool is_offset_initialized() const override { return is_offset_set; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the sections of the segment
//! \return Vector of section indices
const std::vector<Elf_Half>& get_sections() const override const std::vector<Elf_Half>& get_sections() const override
{ {
return sections; return sections;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set the index of the segment
//! \param value Index of the segment
void set_index( const Elf_Half& value ) override { index = value; } void set_index( const Elf_Half& value ) override { index = value; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Load the segment from a stream
//! \param stream Input stream
//! \param header_offset Offset of the segment header
//! \param is_lazy_ Whether to load the segment lazily
//! \return True if successful, false otherwise
bool load( std::istream& stream, bool load( std::istream& stream,
std::streampos header_offset, std::streampos header_offset,
bool is_lazy_ ) override bool is_lazy_ ) override
@ -200,6 +309,8 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Load the data of the segment
//! \return True if successful, false otherwise
bool load_data() const bool load_data() const
{ {
if ( PT_NULL == get_type() || 0 == get_file_size() ) { if ( PT_NULL == get_type() || 0 == get_file_size() ) {
@ -231,6 +342,10 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Save the segment to a stream
//! \param stream Output stream
//! \param header_offset Offset of the segment header
//! \param data_offset Offset of the segment data
void save( std::ostream& stream, void save( std::ostream& stream,
std::streampos header_offset, std::streampos header_offset,
std::streampos data_offset ) override std::streampos data_offset ) override
@ -242,24 +357,32 @@ template <class T> class segment_impl : public segment
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the stream size
//! \return Stream size
size_t get_stream_size() const { return stream_size; } size_t get_stream_size() const { return stream_size; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set the stream size
//! \param value Stream size
void set_stream_size( size_t value ) { stream_size = value; } void set_stream_size( size_t value ) { stream_size = value; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
mutable std::istream* pstream = nullptr; mutable std::istream* pstream = nullptr; //!< Pointer to the input stream
T ph = {}; T ph = {}; //!< Segment header
Elf_Half index = 0; Elf_Half index = 0; //!< Index of the segment
mutable std::unique_ptr<char[]> data; mutable std::unique_ptr<char[]> data; //!< Pointer to the segment data
std::vector<Elf_Half> sections; std::vector<Elf_Half> sections; //!< Vector of section indices
const endianness_convertor* convertor = nullptr; const endianness_convertor* convertor =
const address_translator* translator = nullptr; nullptr; //!< Pointer to the endianness convertor
size_t stream_size = 0; const address_translator* translator =
bool is_offset_set = false; nullptr; //!< Pointer to the address translator
mutable bool is_lazy = false; size_t stream_size = 0; //!< Stream size
mutable bool is_loaded = false; bool is_offset_set = false; //!< Flag indicating if the offset is set
mutable bool is_lazy =
false; //!< Flag indicating if the segment is loaded lazily
mutable bool is_loaded =
false; //!< Flag indicating if the segment is loaded
}; };
} // namespace ELFIO } // namespace ELFIO

View File

@ -30,23 +30,31 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class string_section_accessor_template
//! \brief Class for accessing string section data
template <class S> class string_section_accessor_template template <class S> class string_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param section Pointer to the section
explicit string_section_accessor_template( S* section ) explicit string_section_accessor_template( S* section )
: string_section( section ) : string_section( section )
{ {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get a string from the section
//! \param index Index of the string
//! \return Pointer to the string, or nullptr if not found
const char* get_string( Elf_Word index ) const const char* get_string( Elf_Word index ) const
{ {
if ( string_section ) { if ( string_section ) {
const char* data = string_section->get_data(); const char* data = string_section->get_data();
if ( index < string_section->get_size() && nullptr != data ) { if ( index < string_section->get_size() && nullptr != data ) {
size_t string_length = strnlength( size_t string_length = strnlength(
data + index, string_section->get_size() - index ); data + index,
static_cast<size_t>( string_section->get_size() ) - index );
if ( string_length < ( string_section->get_size() - index ) ) if ( string_length < ( string_section->get_size() - index ) )
return data + index; return data + index;
} }
@ -56,12 +64,15 @@ template <class S> class string_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a string to the section
//! \param str Pointer to the string
//! \return Index of the added string
Elf_Word add_string( const char* str ) Elf_Word add_string( const char* str )
{ {
Elf_Word current_position = 0; Elf_Word current_position = 0;
if ( string_section ) { if ( string_section ) {
// Strings are addeded to the end of the current section data // Strings are added to the end of the current section data
current_position = current_position =
static_cast<Elf_Word>( string_section->get_size() ); static_cast<Elf_Word>( string_section->get_size() );
@ -78,6 +89,9 @@ template <class S> class string_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add a string to the section
//! \param str The string to add
//! \return Index of the added string
Elf_Word add_string( const std::string& str ) Elf_Word add_string( const std::string& str )
{ {
return add_string( str.c_str() ); return add_string( str.c_str() );
@ -85,7 +99,7 @@ template <class S> class string_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
S* string_section; S* string_section; //!< Pointer to the section
}; };
using string_section_accessor = string_section_accessor_template<section>; using string_section_accessor = string_section_accessor_template<section>;

View File

@ -25,10 +25,17 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------
// @class symbol_section_accessor_template
// @brief A template class for accessing symbol sections in an ELF file.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class S> class symbol_section_accessor_template template <class S> class symbol_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------
// @brief Constructor
// @param elf_file Reference to the ELF file
// @param symbol_section Pointer to the symbol section
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
explicit symbol_section_accessor_template( const elfio& elf_file, explicit symbol_section_accessor_template( const elfio& elf_file,
S* symbol_section ) S* symbol_section )
@ -37,6 +44,9 @@ template <class S> class symbol_section_accessor_template
find_hash_section(); find_hash_section();
} }
//------------------------------------------------------------------------------
// @brief Get the number of symbols in the section
// @return Number of symbols
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Xword get_symbols_num() const Elf_Xword get_symbols_num() const
{ {
@ -63,6 +73,17 @@ template <class S> class symbol_section_accessor_template
return nRet; return nRet;
} }
//------------------------------------------------------------------------------
// @brief Get the symbol at the specified index
// @param index Index of the symbol
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param section_index Section index of the symbol
// @param other Other attributes of the symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool get_symbol( Elf_Xword index, bool get_symbol( Elf_Xword index,
std::string& name, std::string& name,
@ -87,6 +108,16 @@ template <class S> class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------
// @brief Get the symbol with the specified name
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param section_index Section index of the symbol
// @param other Other attributes of the symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool get_symbol( const std::string& name, bool get_symbol( const std::string& name,
Elf64_Addr& value, Elf64_Addr& value,
@ -130,6 +161,16 @@ template <class S> class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------
// @brief Get the symbol with the specified value
// @param value Value of the symbol
// @param name Name of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param section_index Section index of the symbol
// @param other Other attributes of the symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool get_symbol( const Elf64_Addr& value, bool get_symbol( const Elf64_Addr& value,
std::string& name, std::string& name,
@ -169,6 +210,15 @@ template <class S> class symbol_section_accessor_template
return false; return false;
} }
//------------------------------------------------------------------------------
// @brief Add a symbol to the section
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param info Info of the symbol
// @param other Other attributes of the symbol
// @param shndx Section index of the symbol
// @return Index of the added symbol
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word add_symbol( Elf_Word name, Elf_Word add_symbol( Elf_Word name,
Elf64_Addr value, Elf64_Addr value,
@ -200,6 +250,16 @@ template <class S> class symbol_section_accessor_template
return nRet; return nRet;
} }
//------------------------------------------------------------------------------
// @brief Add a symbol to the section
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param other Other attributes of the symbol
// @param shndx Section index of the symbol
// @return Index of the added symbol
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word add_symbol( Elf_Word name, Elf_Word add_symbol( Elf_Word name,
Elf64_Addr value, Elf64_Addr value,
@ -213,6 +273,16 @@ template <class S> class symbol_section_accessor_template
shndx ); shndx );
} }
//------------------------------------------------------------------------------
// @brief Add a symbol to the section
// @param pStrWriter String section accessor
// @param str Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param info Info of the symbol
// @param other Other attributes of the symbol
// @param shndx Section index of the symbol
// @return Index of the added symbol
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word add_symbol( string_section_accessor& pStrWriter, Elf_Word add_symbol( string_section_accessor& pStrWriter,
const char* str, const char* str,
@ -226,6 +296,17 @@ template <class S> class symbol_section_accessor_template
return add_symbol( index, value, size, info, other, shndx ); return add_symbol( index, value, size, info, other, shndx );
} }
//------------------------------------------------------------------------------
// @brief Add a symbol to the section
// @param pStrWriter String section accessor
// @param str Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param other Other attributes of the symbol
// @param shndx Section index of the symbol
// @return Index of the added symbol
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Word add_symbol( string_section_accessor& pStrWriter, Elf_Word add_symbol( string_section_accessor& pStrWriter,
const char* str, const char* str,
@ -240,6 +321,10 @@ template <class S> class symbol_section_accessor_template
ELF_ST_INFO( bind, type ), other, shndx ); ELF_ST_INFO( bind, type ), other, shndx );
} }
//------------------------------------------------------------------------------
// @brief Arrange local symbols in the section
// @param func Function to be called for each pair of symbols
// @return Number of local symbols
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Xword arrange_local_symbols( Elf_Xword arrange_local_symbols(
std::function<void( Elf_Xword first, Elf_Xword second )> func = std::function<void( Elf_Xword first, Elf_Xword second )> func =
@ -259,6 +344,8 @@ template <class S> class symbol_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------
// @brief Find the hash section
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void find_hash_section() void find_hash_section()
{ {
@ -276,15 +363,31 @@ template <class S> class symbol_section_accessor_template
} }
} }
//------------------------------------------------------------------------------
// @brief Get the index of the string table
// @return Index of the string table
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half get_string_table_index() const Elf_Half get_string_table_index() const
{ {
return (Elf_Half)symbol_section->get_link(); return (Elf_Half)symbol_section->get_link();
} }
//------------------------------------------------------------------------------
// @brief Get the index of the hash table
// @return Index of the hash table
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Elf_Half get_hash_table_index() const { return hash_section_index; } Elf_Half get_hash_table_index() const { return hash_section_index; }
//------------------------------------------------------------------------------
// @brief Lookup a symbol in the hash table
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param section_index Section index of the symbol
// @param other Other attributes of the symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool hash_lookup( const std::string& name, bool hash_lookup( const std::string& name,
Elf64_Addr& value, Elf64_Addr& value,
@ -323,6 +426,16 @@ template <class S> class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------
// @brief Lookup a symbol in the GNU hash table
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param section_index Section index of the symbol
// @param other Other attributes of the symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> template <class T>
bool gnu_hash_lookup( const std::string& name, bool gnu_hash_lookup( const std::string& name,
@ -391,6 +504,10 @@ template <class S> class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------
// @brief Get the symbol at the specified index
// @param index Index of the symbol
// @return Pointer to the symbol
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> const T* generic_get_symbol_ptr( Elf_Xword index ) const template <class T> const T* generic_get_symbol_ptr( Elf_Xword index ) const
{ {
@ -408,6 +525,11 @@ template <class S> class symbol_section_accessor_template
return nullptr; return nullptr;
} }
//------------------------------------------------------------------------------
// @brief Search for a symbol in the section
// @param match Function to be called for each symbol
// @param idx Index of the found symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> template <class T>
bool generic_search_symbols( std::function<bool( const T* )> match, bool generic_search_symbols( std::function<bool( const T* )> match,
@ -428,6 +550,17 @@ template <class S> class symbol_section_accessor_template
return false; return false;
} }
//------------------------------------------------------------------------------
// @brief Get the symbol at the specified index
// @param index Index of the symbol
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param bind Binding of the symbol
// @param type Type of the symbol
// @param section_index Section index of the symbol
// @param other Other attributes of the symbol
// @return True if the symbol is found, false otherwise
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> template <class T>
bool generic_get_symbol( Elf_Xword index, bool generic_get_symbol( Elf_Xword index,
@ -470,6 +603,15 @@ template <class S> class symbol_section_accessor_template
return ret; return ret;
} }
//------------------------------------------------------------------------------
// @brief Add a symbol to the section
// @param name Name of the symbol
// @param value Value of the symbol
// @param size Size of the symbol
// @param info Info of the symbol
// @param other Other attributes of the symbol
// @param shndx Section index of the symbol
// @return Index of the added symbol
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> template <class T>
Elf_Word generic_add_symbol( Elf_Word name, Elf_Word generic_add_symbol( Elf_Word name,
@ -500,6 +642,10 @@ template <class S> class symbol_section_accessor_template
return nRet; return nRet;
} }
//------------------------------------------------------------------------------
// @brief Arrange local symbols in the section
// @param func Function to be called for each pair of symbols
// @return Number of local symbols
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> template <class T>
Elf_Xword generic_arrange_local_symbols( Elf_Xword generic_arrange_local_symbols(
@ -550,10 +696,10 @@ template <class S> class symbol_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file; ///< Reference to the ELF file
S* symbol_section; S* symbol_section; ///< Pointer to the symbol section
Elf_Half hash_section_index{ 0 }; Elf_Half hash_section_index{ 0 }; ///< Index of the hash section
const section* hash_section{ nullptr }; const section* hash_section{ nullptr }; ///< Pointer to the hash section
}; };
using symbol_section_accessor = symbol_section_accessor_template<section>; using symbol_section_accessor = symbol_section_accessor_template<section>;

View File

@ -56,16 +56,23 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class endianness_convertor
//! \brief Class for converting endianness of data
class endianness_convertor class endianness_convertor
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Setup the endianness convertor
//! \param elf_file_encoding The encoding of the ELF file
void setup( unsigned char elf_file_encoding ) void setup( unsigned char elf_file_encoding )
{ {
need_conversion = ( elf_file_encoding != get_host_encoding() ); need_conversion = ( elf_file_encoding != get_host_encoding() );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a 64-bit unsigned integer
//! \param value The value to convert
//! \return The converted value
uint64_t operator()( uint64_t value ) const uint64_t operator()( uint64_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
@ -84,6 +91,9 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a 64-bit signed integer
//! \param value The value to convert
//! \return The converted value
int64_t operator()( int64_t value ) const int64_t operator()( int64_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
@ -93,6 +103,9 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a 32-bit unsigned integer
//! \param value The value to convert
//! \return The converted value
uint32_t operator()( uint32_t value ) const uint32_t operator()( uint32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
@ -106,6 +119,9 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a 32-bit signed integer
//! \param value The value to convert
//! \return The converted value
int32_t operator()( int32_t value ) const int32_t operator()( int32_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
@ -115,6 +131,9 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a 16-bit unsigned integer
//! \param value The value to convert
//! \return The converted value
uint16_t operator()( uint16_t value ) const uint16_t operator()( uint16_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
@ -127,6 +146,9 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a 16-bit signed integer
//! \param value The value to convert
//! \return The converted value
int16_t operator()( int16_t value ) const int16_t operator()( int16_t value ) const
{ {
if ( !need_conversion ) { if ( !need_conversion ) {
@ -136,14 +158,22 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert an 8-bit signed integer
//! \param value The value to convert
//! \return The converted value
int8_t operator()( int8_t value ) const { return value; } int8_t operator()( int8_t value ) const { return value; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert an 8-bit unsigned integer
//! \param value The value to convert
//! \return The converted value
uint8_t operator()( uint8_t value ) const { return value; } uint8_t operator()( uint8_t value ) const { return value; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the host encoding
//! \return The host encoding
unsigned char get_host_encoding() const unsigned char get_host_encoding() const
{ {
static const int tmp = 1; static const int tmp = 1;
@ -156,24 +186,35 @@ class endianness_convertor
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool need_conversion = false; bool need_conversion = false; //!< Flag indicating if conversion is needed
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \struct address_translation
//! \brief Structure for address translation
struct address_translation struct address_translation
{ {
//------------------------------------------------------------------------------
//! \brief Constructor
//! \param start The start address
//! \param size The size of the address range
//! \param mapped_to The mapped address
address_translation( uint64_t start, uint64_t size, uint64_t mapped_to ) address_translation( uint64_t start, uint64_t size, uint64_t mapped_to )
: start( start ), size( size ), mapped_to( mapped_to ){}; : start( start ), size( size ), mapped_to( mapped_to ){};
std::streampos start; std::streampos start; //!< Start address
std::streampos size; std::streampos size; //!< Size of the address range
std::streampos mapped_to; std::streampos mapped_to; //!< Mapped address
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class address_translator
//! \brief Class for translating addresses
class address_translator class address_translator
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Set address translation
//! \param addr_trans Vector of address translations
void set_address_translation( std::vector<address_translation>& addr_trans ) void set_address_translation( std::vector<address_translation>& addr_trans )
{ {
addr_translations = addr_trans; addr_translations = addr_trans;
@ -186,6 +227,9 @@ class address_translator
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Translate an address
//! \param value The address to translate
//! \return The translated address
std::streampos operator[]( std::streampos value ) const std::streampos operator[]( std::streampos value ) const
{ {
if ( addr_translations.empty() ) { if ( addr_translations.empty() ) {
@ -201,13 +245,20 @@ class address_translator
return value; return value;
} }
//------------------------------------------------------------------------------
//! \brief Check if the address translator is empty
//! \return True if empty, false otherwise
bool empty() const { return addr_translations.empty(); } bool empty() const { return addr_translations.empty(); }
private: private:
std::vector<address_translation> addr_translations; std::vector<address_translation>
addr_translations; //!< Vector of address translations
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Calculate the ELF hash of a name
//! \param name The name to hash
//! \return The ELF hash
inline uint32_t elf_hash( const unsigned char* name ) inline uint32_t elf_hash( const unsigned char* name )
{ {
uint32_t h = 0; uint32_t h = 0;
@ -223,6 +274,9 @@ inline uint32_t elf_hash( const unsigned char* name )
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Calculate the GNU hash of a name
//! \param s The name to hash
//! \return The GNU hash
inline uint32_t elf_gnu_hash( const unsigned char* s ) inline uint32_t elf_gnu_hash( const unsigned char* s )
{ {
uint32_t h = 0x1505; uint32_t h = 0x1505;
@ -232,6 +286,9 @@ inline uint32_t elf_gnu_hash( const unsigned char* s )
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Convert a value to a hexadecimal string
//! \param value The value to convert
//! \return The hexadecimal string
inline std::string to_hex_string( uint64_t value ) inline std::string to_hex_string( uint64_t value )
{ {
std::string str; std::string str;
@ -250,6 +307,9 @@ inline std::string to_hex_string( uint64_t value )
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Adjust the size of a stream
//! \param stream The stream to adjust
//! \param offset The offset to adjust to
inline void adjust_stream_size( std::ostream& stream, std::streamsize offset ) inline void adjust_stream_size( std::ostream& stream, std::streamsize offset )
{ {
stream.seekp( 0, std::ios_base::end ); stream.seekp( 0, std::ios_base::end );
@ -261,43 +321,44 @@ inline void adjust_stream_size( std::ostream& stream, std::streamsize offset )
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the length of a string with a maximum length
//! \param s The string
//! \param n The maximum length
//! \return The length of the string
inline static size_t strnlength( const char* s, size_t n ) inline static size_t strnlength( const char* s, size_t n )
{ {
auto found = (const char*)std::memchr( s, '\0', n ); auto found = (const char*)std::memchr( s, '\0', n );
return found ? (size_t)( found - s ) : n; return found ? (size_t)( found - s ) : n;
} }
/** //------------------------------------------------------------------------------
* Consumers should write an implementation of this class and pass an instance of it to the ELFIO::elfio constructor. //! \class compression_interface
*/ //! \brief Interface for compression and decompression
class compression_interface class compression_interface
{ {
public: public:
virtual ~compression_interface() = default; virtual ~compression_interface() = default;
/**
* decompresses a compressed section //------------------------------------------------------------------------------
* //! \brief Decompress a compressed section
* @param data the buffer of compressed data //! \param data The buffer of compressed data
* @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness. //! \param convertor Pointer to an endianness convertor instance
* @param compressed_size the size of the data buffer, in bytes //! \param compressed_size The size of the compressed data buffer
* @param decompressed_size a reference to a variable where the decompressed buffer size will be stored. //! \param uncompressed_size Reference to a variable to store the decompressed buffer size
* @returns a smart pointer to the decompressed data. //! \return A smart pointer to the decompressed data
*/
virtual std::unique_ptr<char[]> virtual std::unique_ptr<char[]>
inflate( const char* data, inflate( const char* data,
const endianness_convertor* convertor, const endianness_convertor* convertor,
Elf_Xword compressed_size, Elf_Xword compressed_size,
Elf_Xword& uncompressed_size ) const = 0; Elf_Xword& uncompressed_size ) const = 0;
/** //------------------------------------------------------------------------------
* compresses a section //! \brief Compress a section
* //! \param data The buffer of uncompressed data
* @param data the buffer of uncompressed data //! \param convertor Pointer to an endianness convertor instance
* @param endianness_convertor pointer to an endianness_convertor instance, used to convert numbers to/from the target endianness. //! \param decompressed_size The size of the uncompressed data buffer
* @param decompressed_size the size of the data buffer, in bytes //! \param compressed_size Reference to a variable to store the compressed buffer size
* @param compressed_size a reference to a variable where the compressed buffer size will be stored. //! \return A smart pointer to the compressed data
* @returns a smart pointer to the compressed data.
*/
virtual std::unique_ptr<char[]> virtual std::unique_ptr<char[]>
deflate( const char* data, deflate( const char* data,
const endianness_convertor* convertor, const endianness_convertor* convertor,

View File

@ -1 +1,4 @@
//------------------------------------------------------------------------------
//! \def ELFIO_VERSION
//! \brief Defines the version of the ELFIO library
#define ELFIO_VERSION "3.14" #define ELFIO_VERSION "3.14"

View File

@ -26,10 +26,14 @@ THE SOFTWARE.
namespace ELFIO { namespace ELFIO {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class versym_section_accessor_template
//! \brief Class for accessing version symbol section data
template <class S> class versym_section_accessor_template template <class S> class versym_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param section Pointer to the section
explicit versym_section_accessor_template( S* section ) explicit versym_section_accessor_template( S* section )
: versym_section( section ) : versym_section( section )
{ {
@ -40,6 +44,8 @@ template <class S> class versym_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of entries
//! \return Number of entries
Elf_Word get_entries_num() const Elf_Word get_entries_num() const
{ {
if ( versym_section ) { if ( versym_section ) {
@ -49,6 +55,10 @@ template <class S> class versym_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an entry
//! \param no Index of the entry
//! \param value Value of the entry
//! \return True if successful, false otherwise
bool get_entry( Elf_Word no, Elf_Half& value ) const bool get_entry( Elf_Word no, Elf_Half& value ) const
{ {
if ( versym_section && ( no < get_entries_num() ) ) { if ( versym_section && ( no < get_entries_num() ) ) {
@ -60,6 +70,10 @@ template <class S> class versym_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Modify an entry
//! \param no Index of the entry
//! \param value New value of the entry
//! \return True if successful, false otherwise
bool modify_entry( Elf_Word no, Elf_Half value ) bool modify_entry( Elf_Word no, Elf_Half value )
{ {
if ( versym_section && ( no < get_entries_num() ) ) { if ( versym_section && ( no < get_entries_num() ) ) {
@ -71,6 +85,9 @@ template <class S> class versym_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Add an entry
//! \param value Value of the entry
//! \return True if successful, false otherwise
bool add_entry( Elf_Half value ) bool add_entry( Elf_Half value )
{ {
if ( !versym_section ) { if ( !versym_section ) {
@ -85,8 +102,8 @@ template <class S> class versym_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
S* versym_section = nullptr; S* versym_section = nullptr; //!< Pointer to the section
Elf_Word entries_num = 0; Elf_Word entries_num = 0; //!< Number of entries
}; };
using versym_section_accessor = versym_section_accessor_template<section>; using versym_section_accessor = versym_section_accessor_template<section>;
@ -94,10 +111,15 @@ using const_versym_section_accessor =
versym_section_accessor_template<const section>; versym_section_accessor_template<const section>;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class versym_r_section_accessor_template
//! \brief Class for accessing version requirement section data
template <class S> class versym_r_section_accessor_template template <class S> class versym_r_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param elf_file Reference to the ELF file
//! \param versym_r_section Pointer to the version requirement section
versym_r_section_accessor_template( const elfio& elf_file, versym_r_section_accessor_template( const elfio& elf_file,
S* versym_r_section ) S* versym_r_section )
: elf_file( elf_file ), versym_r_section( versym_r_section ), : elf_file( elf_file ), versym_r_section( versym_r_section ),
@ -127,9 +149,20 @@ template <class S> class versym_r_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of entries
//! \return Number of entries
Elf_Word get_entries_num() const { return entries_num; } Elf_Word get_entries_num() const { return entries_num; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an entry
//! \param no Index of the entry
//! \param version Version of the entry
//! \param file_name File name of the entry
//! \param hash Hash of the entry
//! \param flags Flags of the entry
//! \param other Other information of the entry
//! \param dep_name Dependency name of the entry
//! \return True if successful, false otherwise
bool get_entry( Elf_Word no, bool get_entry( Elf_Word no,
Elf_Half& version, Elf_Half& version,
std::string& file_name, std::string& file_name,
@ -166,8 +199,9 @@ template <class S> class versym_r_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file;
S* versym_r_section = nullptr; S* versym_r_section =
Elf_Word entries_num = 0; nullptr; //!< Pointer to the version requirement section
Elf_Word entries_num = 0; //!< Number of entries
}; };
using versym_r_section_accessor = versym_r_section_accessor_template<section>; using versym_r_section_accessor = versym_r_section_accessor_template<section>;
@ -175,10 +209,15 @@ using const_versym_r_section_accessor =
versym_r_section_accessor_template<const section>; versym_r_section_accessor_template<const section>;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \class versym_d_section_accessor_template
//! \brief Class for accessing version definition section data
template <class S> class versym_d_section_accessor_template template <class S> class versym_d_section_accessor_template
{ {
public: public:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Constructor
//! \param elf_file Reference to the ELF file
//! \param versym_d_section Pointer to the version definition section
versym_d_section_accessor_template( const elfio& elf_file, versym_d_section_accessor_template( const elfio& elf_file,
S* versym_d_section ) S* versym_d_section )
: elf_file( elf_file ), versym_d_section( versym_d_section ), : elf_file( elf_file ), versym_d_section( versym_d_section ),
@ -208,9 +247,18 @@ template <class S> class versym_d_section_accessor_template
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get the number of entries
//! \return Number of entries
Elf_Word get_entries_num() const { return entries_num; } Elf_Word get_entries_num() const { return entries_num; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//! \brief Get an entry
//! \param no Index of the entry
//! \param flags Flags of the entry
//! \param version_index Version index of the entry
//! \param hash Hash of the entry
//! \param dep_name Dependency name of the entry
//! \return True if successful, false otherwise
bool get_entry( Elf_Word no, bool get_entry( Elf_Word no,
Elf_Half& flags, Elf_Half& flags,
Elf_Half& version_index, Elf_Half& version_index,
@ -248,8 +296,9 @@ template <class S> class versym_d_section_accessor_template
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
private: private:
const elfio& elf_file; const elfio& elf_file;
S* versym_d_section = nullptr; S* versym_d_section =
Elf_Word entries_num = 0; nullptr; //!< Pointer to the version definition section
Elf_Word entries_num = 0; //!< Number of entries
}; };
using versym_d_section_accessor = versym_d_section_accessor_template<section>; using versym_d_section_accessor = versym_d_section_accessor_template<section>;

View File

@ -1016,7 +1016,7 @@ class mock_wiiu_compression : public compression_interface
{ {
uncompressed_size = 2 * compressed_size; uncompressed_size = 2 * compressed_size;
return std::unique_ptr<char[]>( return std::unique_ptr<char[]>(
new ( std::nothrow ) char[uncompressed_size + 1] ); new ( std::nothrow ) char[static_cast<size_t>(uncompressed_size) + 1] );
} }
std::unique_ptr<char[]> deflate( const char* data, std::unique_ptr<char[]> deflate( const char* data,
@ -1026,7 +1026,7 @@ class mock_wiiu_compression : public compression_interface
{ {
compressed_size = decompressed_size / 2; compressed_size = decompressed_size / 2;
return std::unique_ptr<char[]>( return std::unique_ptr<char[]>(
new ( std::nothrow ) char[compressed_size + 1] ); new ( std::nothrow ) char[static_cast<size_t>(compressed_size) + 1] );
} }
}; };
@ -1131,7 +1131,7 @@ TEST( ELFIOTest, test_free_data )
sec->free_data(); sec->free_data();
EXPECT_TRUE( 0 == std::memcmp( data.data(), sec->get_data(), EXPECT_TRUE( 0 == std::memcmp( data.data(), sec->get_data(),
sec->get_size() ) ); static_cast<size_t>(sec->get_size()) ) );
} }
for ( const auto& seg : reader.segments ) { for ( const auto& seg : reader.segments ) {
@ -1145,7 +1145,7 @@ TEST( ELFIOTest, test_free_data )
seg->free_data(); seg->free_data();
EXPECT_TRUE( 0 == std::memcmp( data.data(), seg->get_data(), EXPECT_TRUE( 0 == std::memcmp( data.data(), seg->get_data(),
seg->get_file_size() ) ); static_cast<size_t>(seg->get_file_size()) ) );
} }
} while ( is_lazy ); } while ( is_lazy );
} }