Initial attempt for lazy load - segment loading

This commit is contained in:
Serge Lamikhov-Center 2022-02-11 10:00:32 +02:00 committed by Serge Lamikhov-Center
parent 92658df379
commit eeb00b60b2
4 changed files with 60 additions and 45 deletions

View File

@ -125,7 +125,7 @@ class elfio
}
//------------------------------------------------------------------------------
bool load( const std::string& file_name )
bool load( const std::string& file_name, bool is_lazy = false )
{
std::ifstream stream;
stream.open( file_name.c_str(), std::ios::in | std::ios::binary );
@ -133,11 +133,11 @@ class elfio
return false;
}
return load( stream );
return load( stream, is_lazy );
}
//------------------------------------------------------------------------------
bool load( std::istream& stream )
bool load( std::istream& stream, bool is_lazy = false )
{
clean();
@ -172,8 +172,8 @@ class elfio
return false;
}
bool is_still_good = load_sections( stream );
is_still_good = is_still_good && load_segments( stream );
load_sections( stream );
bool is_still_good = load_segments( stream, is_lazy );
return is_still_good;
}
@ -532,7 +532,7 @@ class elfio
}
//------------------------------------------------------------------------------
bool load_segments( std::istream& stream )
bool load_segments( std::istream& stream, bool is_lazy )
{
unsigned char file_class = header->get_class();
Elf_Half entry_size = header->get_segment_entry_size();
@ -562,15 +562,9 @@ class elfio
return false;
}
if ( !seg->load( stream, static_cast<std::streamoff>( offset ) +
static_cast<std::streampos>( i ) *
entry_size ) ||
stream.fail() ) {
delete seg;
seg = nullptr;
return false;
}
seg->load( stream,
static_cast<std::streamoff>( offset ) +
static_cast<std::streampos>( i ) * entry_size, is_lazy );
seg->set_index( i );
// Add sections to the segments (similar to readelfs algorithm)

View File

@ -835,7 +835,7 @@ class dump
<< std::endl
<< " Name" << std::endl;
}
for ( Elf_Xword i = 0; i < sym_no; ++i ) {
for ( Elf_Xword j = 0; j < sym_no; ++j ) {
std::string name;
Elf64_Addr value = 0;
Elf_Xword size = 0;
@ -843,9 +843,9 @@ class dump
unsigned char type = 0;
Elf_Half section = 0;
unsigned char other = 0;
symbols.get_symbol( i, name, value, size, bind, type,
symbols.get_symbol( j, name, value, size, bind, type,
section, other );
symbol_table( out, i, name, value, size, bind, type,
symbol_table( out, j, name, value, size, bind, type,
section, reader.get_class() );
}
@ -931,8 +931,7 @@ class dump
note_segment_accessor notes( reader, seg );
Elf_Word no_notes = notes.get_notes_num();
if ( no > 0 ) {
out << "Note segment (" << i << ")"
<< std::endl
out << "Note segment (" << i << ")" << std::endl
<< " No Name Data size Description"
<< std::endl;
for ( Elf_Word j = 0; j < no_notes; ++j ) { // For all notes
@ -993,7 +992,7 @@ class dump
if ( descsz != 0 ) {
for ( Elf_Word i = 0; i < descsz; ++i ) {
if ( i % 16 == 0 ) {
if ( i % 48 == 0 ) {
out << std::endl << " ";
}
out << DUMP_HEX_FORMAT( 2 )
@ -1012,10 +1011,10 @@ class dump
out << "Section .modinfo" << std::endl;
const_modinfo_section_accessor modinfo( sec );
for ( Elf_Word i = 0; i < modinfo.get_attribute_num(); i++ ) {
for ( Elf_Word j = 0; j < modinfo.get_attribute_num(); j++ ) {
std::string field;
std::string value;
if ( modinfo.get_attribute( i, field, value ) ) {
if ( modinfo.get_attribute( j, field, value ) ) {
out << " " << std::setw( 20 ) << field
<< std::setw( 0 ) << " = " << value << std::endl;
}
@ -1041,12 +1040,12 @@ class dump
out << "Dynamic section (" << sec->get_name() << ")"
<< std::endl;
out << "[ Nr ] Tag Name/Value" << std::endl;
for ( Elf_Xword i = 0; i < dyn_no; ++i ) {
for ( Elf_Xword j = 0; j < dyn_no; ++j ) {
Elf_Xword tag = 0;
Elf_Xword value = 0;
std::string str;
dynamic.get_entry( i, tag, value, str );
dynamic_tag( out, i, tag, value, str,
dynamic.get_entry( j, tag, value, str );
dynamic_tag( out, j, tag, value, str,
reader.get_class() );
if ( DT_NULL == tag ) {
break;

View File

@ -60,11 +60,14 @@ class segment
ELFIO_SET_ACCESS_DECL( Elf64_Off, offset );
ELFIO_SET_ACCESS_DECL( Elf_Half, index );
virtual const std::vector<Elf_Half>& get_sections() const = 0;
virtual bool load( std::istream& stream, std::streampos header_offset ) = 0;
virtual const std::vector<Elf_Half>& get_sections() const = 0;
virtual bool load( std::istream& stream,
std::streampos header_offset,
bool is_lazy = false ) = 0;
virtual void save( std::ostream& stream,
std::streampos header_offset,
std::streampos data_offset ) = 0;
std::streampos data_offset ) = 0;
};
//------------------------------------------------------------------------------
@ -72,10 +75,11 @@ template <class T> class segment_impl : public segment
{
public:
//------------------------------------------------------------------------------
segment_impl( const endianess_convertor* convertor,
const address_translator* translator )
: index( 0 ), data( nullptr ), convertor( convertor ),
translator( translator ), stream_size( 0 ), is_offset_set( false )
segment_impl( const endianess_convertor* convertor_,
const address_translator* translator_ )
: pstream( nullptr ), index( 0 ), data( nullptr ),
convertor( convertor_ ), translator( translator_ ), stream_size( 0 ),
is_offset_set( false ), is_lazy( false )
{
std::fill_n( reinterpret_cast<char*>( &ph ), sizeof( ph ), '\0' );
}
@ -98,7 +102,14 @@ template <class T> class segment_impl : public segment
Elf_Half get_index() const override { return index; }
//------------------------------------------------------------------------------
const char* get_data() const override { return data; }
const char* get_data() const override
{
if ( is_lazy ) {
load_data();
is_lazy = false;
}
return data;
}
//------------------------------------------------------------------------------
Elf_Half add_section_index( Elf_Half sec_index,
@ -159,8 +170,13 @@ template <class T> class segment_impl : public segment
void set_index( Elf_Half value ) override { index = value; }
//------------------------------------------------------------------------------
bool load( std::istream& stream, std::streampos header_offset ) override
bool load( std::istream& stream,
std::streampos header_offset,
bool is_lazy_ = false ) override
{
pstream = &stream;
is_lazy = is_lazy_;
if ( translator->empty() ) {
stream.seekg( 0, stream.end );
set_stream_size( size_t( stream.tellg() ) );
@ -173,23 +189,27 @@ template <class T> class segment_impl : public segment
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
is_offset_set = true;
if ( !is_lazy ) {
return load_data();
}
return true;
}
bool load_data() const
{
if ( PT_NULL != get_type() && 0 != get_file_size() ) {
stream.seekg( ( *translator )[( *convertor )( ph.p_offset )] );
pstream->seekg( ( *translator )[( *convertor )( ph.p_offset )] );
Elf_Xword size = get_file_size();
if ( size > get_stream_size() ) {
if ( size > get_stream_size() || is_lazy ) {
data = nullptr;
}
else {
data = new ( std::nothrow ) char[(size_t)size + 1];
if ( nullptr != data ) {
stream.read( data, size );
if (stream.gcount() != size) {
delete[] data;
data = nullptr;
return false;
}
pstream->read( data, size );
data[size] = 0;
}
}
@ -217,14 +237,16 @@ template <class T> class segment_impl : public segment
//------------------------------------------------------------------------------
private:
mutable std::istream* pstream;
T ph;
Elf_Half index;
char* data;
mutable char* data;
std::vector<Elf_Half> sections;
const endianess_convertor* convertor;
const address_translator* translator;
size_t stream_size;
bool is_offset_set;
mutable bool is_lazy;
};
} // namespace ELFIO

View File

@ -82,7 +82,7 @@ int main( int argc, char** argv )
elffile.set_address_translation( ranges );
// The 'load' will use the provided address translation now
if ( elffile.load( std::string( "/proc/" ) + argv[1] + "/mem" ) ) {
if ( elffile.load( std::string( "/proc/" ) + argv[1] + "/mem", true ) ) {
dump::header( std::cout, elffile );
dump::segment_headers( std::cout, elffile );
dump::segment_datas( std::cout, elffile );