diff --git a/doc/elfio.docx b/doc/elfio.docx index d6a2ee4..d0a9fd2 100644 Binary files a/doc/elfio.docx and b/doc/elfio.docx differ diff --git a/doc/elfio.pdf b/doc/elfio.pdf index 6c79587..486388c 100644 Binary files a/doc/elfio.pdf and b/doc/elfio.pdf differ diff --git a/elfio/elfio_section.hpp b/elfio/elfio_section.hpp index 8c6aed4..593f255 100644 --- a/elfio/elfio_section.hpp +++ b/elfio/elfio_section.hpp @@ -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 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 section_impl : public section stream.seekg( ( *translator )[header_offset] ); stream.read( reinterpret_cast( &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 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 section_impl : public section } } + is_loaded = true; + return true; } @@ -338,7 +348,7 @@ template 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 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 diff --git a/elfio/elfio_segment.hpp b/elfio/elfio_segment.hpp index 371e0fa..d805244 100644 --- a/elfio/elfio_segment.hpp +++ b/elfio/elfio_segment.hpp @@ -99,7 +99,7 @@ template 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 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 segment_impl : public segment stream.read( reinterpret_cast( &ph ), sizeof( ph ) ); is_offset_set = true; - if ( !is_lazy ) { + if ( !( is_lazy || is_loaded ) ) { return load_data(); } @@ -200,7 +202,6 @@ template 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 segment_impl : public segment } } + is_loaded = true; + return true; } @@ -255,6 +258,7 @@ template 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 diff --git a/tests/ELFIOTest.cpp b/tests/ELFIOTest.cpp index fa2d62c..6981d3b 100644 --- a/tests/ELFIOTest.cpp +++ b/tests/ELFIOTest.cpp @@ -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 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 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 ); +}