mirror of
https://github.com/serge1/ELFIO.git
synced 2025-01-29 21:32:44 +00:00
Initial attempt for lazy load - segment loading
This commit is contained in:
parent
92658df379
commit
eeb00b60b2
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user