From 156cac5fa1a61b865e29f40cf7030f6618747c50 Mon Sep 17 00:00:00 2001 From: Serge Lamikhov-Center Date: Tue, 30 Aug 2022 19:42:28 +0300 Subject: [PATCH] Modernize the section implementation --- elfio/elfio.hpp | 80 +++++++++++++++++++++-------------------- elfio/elfio_section.hpp | 79 ++++++++++++++++++---------------------- 2 files changed, 75 insertions(+), 84 deletions(-) diff --git a/elfio/elfio.hpp b/elfio/elfio.hpp index f80deca..4532271 100644 --- a/elfio/elfio.hpp +++ b/elfio/elfio.hpp @@ -140,10 +140,10 @@ class elfio sections_.clear(); segments_.clear(); - unsigned char e_ident[EI_NIDENT] = { 0 }; + std::array e_ident = { 0 }; // Read ELF file signature stream.seekg( addr_translator[0] ); - stream.read( reinterpret_cast( &e_ident ), sizeof( e_ident ) ); + stream.read( e_ident.data(), sizeof( e_ident ) ); // Is it ELF file? if ( stream.gcount() != sizeof( e_ident ) || @@ -313,6 +313,7 @@ class elfio } } } + // clang-format on // Check for conflicting section / program header tables, where // the same offset has different vaddresses in section table and @@ -324,15 +325,20 @@ class elfio // since offsets are re-calculated from vaddress for ( int h = 0; h < segments.size(); ++h ) { const segment* seg = segments[h]; - if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 ) { - const section* sec = find_prog_section_for_offset( seg->get_offset() ); - if ( sec != nullptr ) { - Elf64_Addr sec_addr = get_virtual_addr( seg->get_offset(), sec ); - if ( sec_addr != seg->get_virtual_address() ) { - errors += "Virtual address of segment " + std::to_string( h ) + " (" + to_hex_string( seg->get_virtual_address() ) + ")" - + " conflicts with address of section " + sec->get_name() + " (" + to_hex_string( sec_addr ) + ")" - + " at offset " + to_hex_string( seg->get_offset() ) + "\n"; - } + const section* sec = + find_prog_section_for_offset( seg->get_offset() ); + if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 && + sec != nullptr ) { + Elf64_Addr sec_addr = + get_virtual_addr( seg->get_offset(), sec ); + if ( sec_addr != seg->get_virtual_address() ) { + errors += "Virtual address of segment " + + std::to_string( h ) + " (" + + to_hex_string( seg->get_virtual_address() ) + + ")" + " conflicts with address of section " + + sec->get_name() + " (" + + to_hex_string( sec_addr ) + ")" + " at offset " + + to_hex_string( seg->get_offset() ) + "\n"; } } } @@ -340,7 +346,6 @@ class elfio // more checks to be added here... return errors; - // clang-format on } private: @@ -395,23 +400,23 @@ class elfio //------------------------------------------------------------------------------ section* create_section() { - section* new_section = nullptr; - unsigned char file_class = get_class(); + unsigned char file_class = get_class(); if ( file_class == ELFCLASS64 ) { - new_section = - new section_impl( &convertor, &addr_translator ); + sections_.emplace_back( + new section_impl( &convertor, &addr_translator ) ); } else if ( file_class == ELFCLASS32 ) { - new_section = - new section_impl( &convertor, &addr_translator ); + sections_.emplace_back( + new section_impl( &convertor, &addr_translator ) ); } else { + sections_.pop_back(); return nullptr; } - new_section->set_index( static_cast( sections_.size() ) ); - sections_.emplace_back( new_section ); + section* new_section = sections_.back().get(); + new_section->set_index( static_cast( sections_.size() - 1 ) ); return new_section; } @@ -419,23 +424,23 @@ class elfio //------------------------------------------------------------------------------ segment* create_segment() { - segment* new_segment = nullptr; - unsigned char file_class = header->get_class(); + unsigned char file_class = header->get_class(); if ( file_class == ELFCLASS64 ) { - new_segment = - new segment_impl( &convertor, &addr_translator ); + segments_.emplace_back( + new segment_impl( &convertor, &addr_translator ) ); } else if ( file_class == ELFCLASS32 ) { - new_segment = - new segment_impl( &convertor, &addr_translator ); + segments_.emplace_back( + new segment_impl( &convertor, &addr_translator ) ); } else { + segments_.pop_back(); return nullptr; } - new_segment->set_index( static_cast( segments_.size() ) ); - segments_.emplace_back( new_segment ); + segment* new_segment = segments_.back().get(); + new_segment->set_index( static_cast( segments_.size() - 1 ) ); return new_segment; } @@ -530,26 +535,26 @@ class elfio } for ( Elf_Half i = 0; i < num; ++i ) { - segment* seg = nullptr; - if ( file_class == ELFCLASS64 ) { - seg = new segment_impl( &convertor, - &addr_translator ); + segments_.emplace_back( new segment_impl( + &convertor, &addr_translator ) ); } else if ( file_class == ELFCLASS32 ) { - seg = new segment_impl( &convertor, - &addr_translator ); + segments_.emplace_back( new segment_impl( + &convertor, &addr_translator ) ); } else { + segments_.pop_back(); return false; } + segment* seg = segments_.back().get(); + if ( !seg->load( stream, static_cast( offset ) + static_cast( i ) * entry_size ) || stream.fail() ) { - delete seg; - seg = nullptr; + segments_.pop_back(); return false; } @@ -574,9 +579,6 @@ class elfio seg->add_section_index( psec->get_index(), 0 ); } } - - // Add section into the segments' container - segments_.emplace_back( seg ); } return true; diff --git a/elfio/elfio_section.hpp b/elfio/elfio_section.hpp index a653356..4bb42c2 100644 --- a/elfio/elfio_section.hpp +++ b/elfio/elfio_section.hpp @@ -50,13 +50,13 @@ class section ELFIO_GET_SET_ACCESS_DECL( Elf_Word, name_string_offset ); ELFIO_GET_ACCESS_DECL( Elf64_Off, offset ); - virtual const char* get_data() const = 0; - virtual void set_data( const char* pData, Elf_Word size ) = 0; - virtual void set_data( const std::string& data ) = 0; - virtual void append_data( const char* pData, Elf_Word size ) = 0; - virtual void append_data( const std::string& data ) = 0; - virtual size_t get_stream_size() const = 0; - virtual void set_stream_size( size_t value ) = 0; + virtual const char* get_data() const = 0; + virtual void set_data( const char* raw_data, Elf_Word size ) = 0; + virtual void set_data( const std::string& data ) = 0; + virtual void append_data( const char* raw_data, Elf_Word size ) = 0; + virtual void append_data( const std::string& data ) = 0; + virtual size_t get_stream_size() const = 0; + virtual void set_stream_size( size_t value ) = 0; protected: ELFIO_SET_ACCESS_DECL( Elf64_Off, offset ); @@ -77,18 +77,8 @@ template class section_impl : public section const address_translator* translator ) : convertor( convertor ), translator( translator ) { - std::fill_n( reinterpret_cast( &header ), sizeof( header ), - '\0' ); - is_address_set = false; - data = nullptr; - data_size = 0; - index = 0; - stream_size = 0; } - //------------------------------------------------------------------------------ - ~section_impl() override { delete[] data; } - //------------------------------------------------------------------------------ // Section info functions ELFIO_GET_SET_ACCESS( Elf_Word, type, header.sh_type ); @@ -122,17 +112,16 @@ template class section_impl : public section bool is_address_initialized() const override { return is_address_set; } //------------------------------------------------------------------------------ - const char* get_data() const override { return data; } + const char* get_data() const override { return data.get(); } //------------------------------------------------------------------------------ void set_data( const char* raw_data, Elf_Word size ) override { if ( get_type() != SHT_NOBITS ) { - delete[] data; - data = new ( std::nothrow ) char[size]; - if ( nullptr != data && nullptr != raw_data ) { + data = std::unique_ptr( new ( std::nothrow ) char[size] ); + if ( nullptr != data.get() && nullptr != raw_data ) { data_size = size; - std::copy( raw_data, raw_data + size, data ); + std::copy( raw_data, raw_data + size, data.get() ); } else { data_size = 0; @@ -156,18 +145,19 @@ template class section_impl : public section { if ( get_type() != SHT_NOBITS ) { if ( get_size() + size < data_size ) { - std::copy( raw_data, raw_data + size, data + get_size() ); + std::copy( raw_data, raw_data + size, data.get() + get_size() ); } else { - data_size = 2 * ( data_size + size ); - char* new_data = new ( std::nothrow ) char[data_size]; + data_size = 2 * ( data_size + size ); + std::unique_ptr new_data( + new ( std::nothrow ) char[data_size] ); if ( nullptr != new_data ) { - std::copy( data, data + get_size(), new_data ); + std::copy( data.get(), data.get() + get_size(), + new_data.get() ); std::copy( raw_data, raw_data + size, - new_data + get_size() ); - delete[] data; - data = new_data; + new_data.get() + get_size() ); + data = std::move( new_data ); } else { size = 0; @@ -203,8 +193,7 @@ template class section_impl : public section //------------------------------------------------------------------------------ bool load( std::istream& stream, std::streampos header_offset ) override { - std::fill_n( reinterpret_cast( &header ), sizeof( header ), - '\0' ); + header = { 0 }; if ( translator->empty() ) { stream.seekg( 0, std::istream::end ); @@ -220,19 +209,19 @@ template class section_impl : public section Elf_Xword size = get_size(); if ( nullptr == data && SHT_NULL != get_type() && SHT_NOBITS != get_type() && size < get_stream_size() ) { - data = new ( std::nothrow ) char[size_t( size ) + 1]; + data.reset( new ( std::nothrow ) char[size_t( size ) + 1] ); if ( ( 0 != size ) && ( nullptr != data ) ) { stream.seekg( ( *translator )[( *convertor )( header.sh_offset )] ); - stream.read( data, size ); - if (static_cast(stream.gcount()) != size) { - delete[] data; + stream.read( data.get(), size ); + if ( static_cast( stream.gcount() ) != size ) { data = nullptr; return false; } - data[size] = 0; // Ensure data is ended with 0 to avoid oob read - data_size = decltype( data_size )( size ); + data.get()[size] = + 0; // Ensure data is ended with 0 to avoid oob read + data_size = decltype( data_size )( size ); } else { data_size = 0; @@ -278,15 +267,15 @@ template class section_impl : public section //------------------------------------------------------------------------------ private: - T header; - Elf_Half index; + T header = { 0 }; + Elf_Half index = 0; std::string name; - char* data; - Elf_Word data_size; - const endianess_convertor* convertor; - const address_translator* translator; - bool is_address_set; - size_t stream_size; + std::unique_ptr data; + Elf_Word data_size = 0; + const endianess_convertor* convertor = 0; + const address_translator* translator = 0; + bool is_address_set = false; + size_t stream_size = 0; }; } // namespace ELFIO