mirror of
https://github.com/serge1/ELFIO.git
synced 2024-11-19 11:14:46 +00:00
Modernize the section implementation
This commit is contained in:
parent
d4295a5ec9
commit
156cac5fa1
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user