Modernize the section implementation

This commit is contained in:
Serge Lamikhov-Center 2022-08-30 19:42:28 +03:00
parent d4295a5ec9
commit 156cac5fa1
2 changed files with 75 additions and 84 deletions

View File

@ -140,10 +140,10 @@ class elfio
sections_.clear();
segments_.clear();
unsigned char e_ident[EI_NIDENT] = { 0 };
std::array<char, EI_NIDENT> e_ident = { 0 };
// Read ELF file signature
stream.seekg( addr_translator[0] );
stream.read( reinterpret_cast<char*>( &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<Elf64_Shdr>( &convertor, &addr_translator );
sections_.emplace_back(
new section_impl<Elf64_Shdr>( &convertor, &addr_translator ) );
}
else if ( file_class == ELFCLASS32 ) {
new_section =
new section_impl<Elf32_Shdr>( &convertor, &addr_translator );
sections_.emplace_back(
new section_impl<Elf32_Shdr>( &convertor, &addr_translator ) );
}
else {
sections_.pop_back();
return nullptr;
}
new_section->set_index( static_cast<Elf_Half>( sections_.size() ) );
sections_.emplace_back( new_section );
section* new_section = sections_.back().get();
new_section->set_index( static_cast<Elf_Half>( 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<Elf64_Phdr>( &convertor, &addr_translator );
segments_.emplace_back(
new segment_impl<Elf64_Phdr>( &convertor, &addr_translator ) );
}
else if ( file_class == ELFCLASS32 ) {
new_segment =
new segment_impl<Elf32_Phdr>( &convertor, &addr_translator );
segments_.emplace_back(
new segment_impl<Elf32_Phdr>( &convertor, &addr_translator ) );
}
else {
segments_.pop_back();
return nullptr;
}
new_segment->set_index( static_cast<Elf_Half>( segments_.size() ) );
segments_.emplace_back( new_segment );
segment* new_segment = segments_.back().get();
new_segment->set_index( static_cast<Elf_Half>( 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<Elf64_Phdr>( &convertor,
&addr_translator );
segments_.emplace_back( new segment_impl<Elf64_Phdr>(
&convertor, &addr_translator ) );
}
else if ( file_class == ELFCLASS32 ) {
seg = new segment_impl<Elf32_Phdr>( &convertor,
&addr_translator );
segments_.emplace_back( new segment_impl<Elf32_Phdr>(
&convertor, &addr_translator ) );
}
else {
segments_.pop_back();
return false;
}
segment* seg = segments_.back().get();
if ( !seg->load( stream, static_cast<std::streamoff>( offset ) +
static_cast<std::streampos>( 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;

View File

@ -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 T> class section_impl : public section
const address_translator* translator )
: convertor( convertor ), translator( translator )
{
std::fill_n( reinterpret_cast<char*>( &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 T> 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<char>( 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 T> 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<char> 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 T> class section_impl : public section
//------------------------------------------------------------------------------
bool load( std::istream& stream, std::streampos header_offset ) override
{
std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ),
'\0' );
header = { 0 };
if ( translator->empty() ) {
stream.seekg( 0, std::istream::end );
@ -220,19 +209,19 @@ template <class T> 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<Elf_Xword>(stream.gcount()) != size) {
delete[] data;
stream.read( data.get(), size );
if ( static_cast<Elf_Xword>( 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 T> 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<char> 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