Skip to content

Commit

Permalink
Implement free_data() for sections too
Browse files Browse the repository at this point in the history
free_data() has no effect if is_lazy was not set
  • Loading branch information
Serge Lamikhov-Center committed Oct 13, 2023
1 parent 0399b9f commit c86883b
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
Binary file modified doc/elfio.docx
Binary file not shown.
Binary file modified doc/elfio.pdf
Binary file not shown.
23 changes: 17 additions & 6 deletions elfio/elfio_section.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class section
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );

virtual const char* get_data() const = 0;
virtual void free_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;
Expand Down Expand Up @@ -123,12 +124,21 @@ template <class T> class section_impl : public section
//------------------------------------------------------------------------------
const char* get_data() const override
{
if ( is_lazy ) {
if ( !is_loaded ) {
load_data();
}
return data.get();
}

//------------------------------------------------------------------------------
void free_data() const override
{
if ( is_lazy ) {
data.reset( nullptr );
is_loaded = false;
}
}

//------------------------------------------------------------------------------
void set_data( const char* raw_data, Elf_Word size ) override
{
Expand Down Expand Up @@ -248,15 +258,14 @@ template <class T> class section_impl : public section
stream.seekg( ( *translator )[header_offset] );
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );

if ( !is_lazy || is_compressed() ) {

if ( !( is_lazy || is_loaded ) ) {
bool ret = load_data();

if ( is_compressed() ) {
Elf_Xword size = get_size();
Elf_Xword uncompressed_size = 0;
auto decompressed_data = compression->inflate(
data.get(), convertor, size, uncompressed_size );
data.get(), convertor, size, uncompressed_size );
if ( decompressed_data != nullptr ) {
set_size( uncompressed_size );
data = std::move( decompressed_data );
Expand All @@ -271,7 +280,6 @@ template <class T> class section_impl : public section

bool load_data() const
{
is_lazy = false;
Elf_Xword size = get_size();
if ( nullptr == data && SHT_NULL != get_type() &&
SHT_NOBITS != get_type() && size < get_stream_size() ) {
Expand All @@ -297,6 +305,8 @@ template <class T> class section_impl : public section
}
}

is_loaded = true;

return true;
}

Expand Down Expand Up @@ -338,7 +348,7 @@ template <class T> class section_impl : public section
Elf_Xword decompressed_size = get_size();
Elf_Xword compressed_size = 0;
auto compressed_ptr = compression->deflate(
data.get(), convertor, decompressed_size, compressed_size );
data.get(), convertor, decompressed_size, compressed_size );
stream.write( compressed_ptr.get(), compressed_size );
}
else {
Expand All @@ -360,6 +370,7 @@ template <class T> class section_impl : public section
bool is_address_set = false;
size_t stream_size = 0;
mutable bool is_lazy = false;
mutable bool is_loaded = false;
};

} // namespace ELFIO
Expand Down
14 changes: 9 additions & 5 deletions elfio/elfio_segment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ template <class T> class segment_impl : public segment
//------------------------------------------------------------------------------
const char* get_data() const override
{
if ( is_lazy ) {
if ( !is_loaded ) {
load_data();
}
return data.get();
Expand All @@ -108,8 +108,10 @@ template <class T> class segment_impl : public segment
//------------------------------------------------------------------------------
void free_data() const override
{
data.reset( nullptr );
is_lazy = true;
if ( is_lazy ) {
data.reset( nullptr );
is_loaded = false;
}
}

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -190,7 +192,7 @@ template <class T> class segment_impl : public segment
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
is_offset_set = true;

if ( !is_lazy ) {
if ( !( is_lazy || is_loaded ) ) {
return load_data();
}

Expand All @@ -200,7 +202,6 @@ template <class T> class segment_impl : public segment
//------------------------------------------------------------------------------
bool load_data() const
{
is_lazy = false;
if ( PT_NULL == get_type() || 0 == get_file_size() ) {
return true;
}
Expand All @@ -223,6 +224,8 @@ template <class T> class segment_impl : public segment
}
}

is_loaded = true;

return true;
}

Expand Down Expand Up @@ -255,6 +258,7 @@ template <class T> class segment_impl : public segment
size_t stream_size = 0;
bool is_offset_set = false;
mutable bool is_lazy = false;
mutable bool is_loaded = false;
};

} // namespace ELFIO
Expand Down
65 changes: 64 additions & 1 deletion tests/ELFIOTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,48 +211,59 @@ TEST( ELFIOTest, load32 )
////////////////////////////////////////////////////////////////////////////
// Check sections
const section* sec = reader.sections[0];
// sec->free_data();
checkSection( sec, 0, "", SHT_NULL, 0, 0, 0, 0, 0, 0, 0 );

sec = reader.sections[1];
// sec->free_data();
checkSection( sec, 1, ".interp", SHT_PROGBITS, SHF_ALLOC, 0x08048114,
0x13, 0, 0, 1, 0 );

sec = reader.sections[9];
// sec->free_data();
checkSection( sec, 9, ".rel.plt", SHT_REL, SHF_ALLOC, 0x08048234, 0x18,
4, 11, 4, 8 );

sec = reader.sections[19];
// sec->free_data();
checkSection( sec, 19, ".dynamic", SHT_DYNAMIC, SHF_WRITE | SHF_ALLOC,
0x080494a0, 0xc8, 5, 0, 4, 8 );

sec = reader.sections[27];
// sec->free_data();
checkSection( sec, 27, ".strtab", SHT_STRTAB, 0, 0x0, 0x259, 0, 0, 1,
0 );

for ( Elf_Half i = 0; i < reader.sections.size(); ++i ) {
sec = reader.sections[i];
// sec->free_data();
EXPECT_EQ( sec->get_index(), i );
}

const section* sec1 = reader.sections[".strtab"];
// sec1->free_data();
EXPECT_EQ( sec->get_index(), sec1->get_index() );

////////////////////////////////////////////////////////////////////////////
// Check segments
const segment* seg = reader.segments[0];
seg->free_data();
checkSegment( seg, PT_PHDR, 0x08048034, 0x08048034, 0x000e0, 0x000e0,
PF_R + PF_X, 4 );

seg = reader.segments[4];
seg->free_data();
checkSegment( seg, PT_DYNAMIC, 0x080494a0, 0x080494a0, 0x000c8, 0x000c8,
PF_R + PF_W, 4 );

seg = reader.segments[6];
seg->free_data();
checkSegment( seg, 0x6474E551, 0x0, 0x0, 0x0, 0x0, PF_R + PF_W, 4 );

////////////////////////////////////////////////////////////////////////////
// Check symbol table
sec = reader.sections[".symtab"];
// sec->free_data();

const_symbol_section_accessor sr( reader, sec );

Expand All @@ -274,6 +285,7 @@ TEST( ELFIOTest, load32 )
////////////////////////////////////////////////////////////////////////////
// Check relocation table
sec = reader.sections[".rel.dyn"];
// sec->free_data();

const_relocation_section_accessor reloc( reader, sec );
EXPECT_EQ( reloc.get_entries_num(), 1 );
Expand All @@ -282,6 +294,7 @@ TEST( ELFIOTest, load32 )
R_386_GLOB_DAT, 0, 0 );

sec = reader.sections[".rel.plt"];
// sec->free_data();

const_relocation_section_accessor reloc1( reader, sec );
EXPECT_EQ( reloc1.get_entries_num(), 3 );
Expand Down Expand Up @@ -322,26 +335,30 @@ TEST( ELFIOTest, load64 )
////////////////////////////////////////////////////////////////////////////
// Check sections
const section* sec = reader.sections[0];
// sec->free_data();

checkSection( sec, 0, "", SHT_NULL, 0, 0, 0, 0, 0, 0, 0 );

sec = reader.sections[1];
// sec->free_data();

checkSection( sec, 1, ".interp", SHT_PROGBITS, SHF_ALLOC,
0x0000000000400200, 0x1c, 0, 0, 1, 0 );

sec = reader.sections[9];
// sec->free_data();

checkSection( sec, 9, ".rela.plt", SHT_RELA, SHF_ALLOC,
0x0000000000400340, 0x30, 4, 11, 8, 0x18 );

sec = reader.sections[20];
// sec->free_data();

checkSection( sec, 20, ".dynamic", SHT_DYNAMIC, SHF_WRITE | SHF_ALLOC,
0x0000000000600698, 0x190, 5, 0, 8, 0x10 );

sec = reader.sections[28];

// sec->free_data();
checkSection( sec, 28, ".strtab", SHT_STRTAB, 0, 0x0, 0x23f, 0, 0, 1,
0 );

Expand All @@ -351,20 +368,24 @@ TEST( ELFIOTest, load64 )
////////////////////////////////////////////////////////////////////////////
// Check segments
const segment* seg = reader.segments[0];
seg->free_data();
checkSegment( seg, PT_PHDR, 0x0000000000400040, 0x0000000000400040,
0x00000000000001c0, 0x00000000000001c0, PF_R + PF_X, 8 );

seg = reader.segments[2];
seg->free_data();
checkSegment( seg, PT_LOAD, 0x0000000000400000, 0x0000000000400000,
0x000000000000066c, 0x000000000000066c, PF_R + PF_X,
0x200000 );

seg = reader.segments[7];
seg->free_data();
checkSegment( seg, 0x6474E551, 0x0, 0x0, 0x0, 0x0, PF_R + PF_W, 8 );

////////////////////////////////////////////////////////////////////////////
// Check symbol table
sec = reader.sections[".symtab"];
// sec->free_data();

const_symbol_section_accessor sr( reader, sec );

Expand All @@ -387,6 +408,7 @@ TEST( ELFIOTest, load64 )
////////////////////////////////////////////////////////////////////////////
// Check relocation table
sec = reader.sections[".rela.dyn"];
// sec->free_data();

const_relocation_section_accessor reloc( reader, sec );
EXPECT_EQ( reloc.get_entries_num(), 1 );
Expand All @@ -407,6 +429,7 @@ TEST( ELFIOTest, load64 )
////////////////////////////////////////////////////////////////////////////
// Check note reader
sec = reader.sections[".note.ABI-tag"];
// sec->free_data();

const_note_section_accessor notes( reader, sec );
EXPECT_EQ( notes.get_notes_num(), 1u );
Expand Down Expand Up @@ -1086,3 +1109,43 @@ TEST( ELFIOTest, test_dynamic_64_3 )
}
}
}

TEST( ELFIOTest, test_is_lazy )
{
bool is_lazy = false;
do {
is_lazy = !is_lazy;

elfio reader;

ASSERT_EQ( reader.load( "elf_examples/main", is_lazy ), true );

for ( const auto& sec : reader.sections ) {
if ( sec->get_size() == 0 || sec->get_data() == nullptr )
continue;

std::vector<char> data;
std::copy( sec->get_data(), sec->get_data() + sec->get_size(),
std::back_inserter( data ) );

sec->free_data();

EXPECT_TRUE( 0 == std::memcmp( data.data(), sec->get_data(),
sec->get_size() ) );
}

for ( const auto& seg : reader.segments ) {
if ( seg->get_file_size() == 0 || seg->get_data() == nullptr )
continue;

std::vector<char> data;
std::copy( seg->get_data(), seg->get_data() + seg->get_file_size(),
std::back_inserter( data ) );

seg->free_data();

EXPECT_TRUE( 0 == std::memcmp( data.data(), seg->get_data(),
seg->get_file_size() ) );
}
} while ( is_lazy );
}

0 comments on commit c86883b

Please sign in to comment.