Implement free_data() for sections too

free_data() has no effect if is_lazy was not set
This commit is contained in:
Serge Lamikhov-Center 2023-10-13 20:03:48 +03:00
parent 0399b9f8df
commit c86883b906
5 changed files with 90 additions and 12 deletions

Binary file not shown.

Binary file not shown.

View File

@ -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;
@ -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
{
@ -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 );
@ -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() ) {
@ -297,6 +305,8 @@ template <class T> class section_impl : public section
}
}
is_loaded = true;
return true;
}
@ -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 {
@ -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

View File

@ -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();
@ -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;
}
}
//------------------------------------------------------------------------------
@ -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();
}
@ -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;
}
@ -223,6 +224,8 @@ template <class T> class segment_impl : public segment
}
}
is_loaded = true;
return true;
}
@ -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

View File

@ -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 );
@ -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 );
@ -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 );
@ -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 );
@ -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 );
@ -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 );
@ -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 );
@ -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 );
}