mirror of
https://github.com/serge1/ELFIO.git
synced 2024-12-26 18:15:40 +00:00
Implement free_data() for sections too
free_data() has no effect if is_lazy was not set
This commit is contained in:
parent
0399b9f8df
commit
c86883b906
BIN
doc/elfio.docx
BIN
doc/elfio.docx
Binary file not shown.
BIN
doc/elfio.pdf
BIN
doc/elfio.pdf
Binary file not shown.
@ -51,6 +51,7 @@ class section
|
|||||||
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
ELFIO_GET_ACCESS_DECL( Elf64_Off, offset );
|
||||||
|
|
||||||
virtual const char* get_data() const = 0;
|
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 char* raw_data, Elf_Word size ) = 0;
|
||||||
virtual void set_data( const std::string& data ) = 0;
|
virtual void set_data( const std::string& data ) = 0;
|
||||||
virtual void append_data( const char* raw_data, Elf_Word size ) = 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
|
const char* get_data() const override
|
||||||
{
|
{
|
||||||
if ( is_lazy ) {
|
if ( !is_loaded ) {
|
||||||
load_data();
|
load_data();
|
||||||
}
|
}
|
||||||
return data.get();
|
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
|
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.seekg( ( *translator )[header_offset] );
|
||||||
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) );
|
||||||
|
|
||||||
if ( !is_lazy || is_compressed() ) {
|
if ( !( is_lazy || is_loaded ) ) {
|
||||||
|
|
||||||
bool ret = load_data();
|
bool ret = load_data();
|
||||||
|
|
||||||
if ( is_compressed() ) {
|
if ( is_compressed() ) {
|
||||||
Elf_Xword size = get_size();
|
Elf_Xword size = get_size();
|
||||||
Elf_Xword uncompressed_size = 0;
|
Elf_Xword uncompressed_size = 0;
|
||||||
auto decompressed_data = compression->inflate(
|
auto decompressed_data = compression->inflate(
|
||||||
data.get(), convertor, size, uncompressed_size );
|
data.get(), convertor, size, uncompressed_size );
|
||||||
if ( decompressed_data != nullptr ) {
|
if ( decompressed_data != nullptr ) {
|
||||||
set_size( uncompressed_size );
|
set_size( uncompressed_size );
|
||||||
data = std::move( decompressed_data );
|
data = std::move( decompressed_data );
|
||||||
@ -271,7 +280,6 @@ template <class T> class section_impl : public section
|
|||||||
|
|
||||||
bool load_data() const
|
bool load_data() const
|
||||||
{
|
{
|
||||||
is_lazy = false;
|
|
||||||
Elf_Xword size = get_size();
|
Elf_Xword size = get_size();
|
||||||
if ( nullptr == data && SHT_NULL != get_type() &&
|
if ( nullptr == data && SHT_NULL != get_type() &&
|
||||||
SHT_NOBITS != get_type() && size < get_stream_size() ) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +348,7 @@ template <class T> class section_impl : public section
|
|||||||
Elf_Xword decompressed_size = get_size();
|
Elf_Xword decompressed_size = get_size();
|
||||||
Elf_Xword compressed_size = 0;
|
Elf_Xword compressed_size = 0;
|
||||||
auto compressed_ptr = compression->deflate(
|
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 );
|
stream.write( compressed_ptr.get(), compressed_size );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -360,6 +370,7 @@ template <class T> class section_impl : public section
|
|||||||
bool is_address_set = false;
|
bool is_address_set = false;
|
||||||
size_t stream_size = 0;
|
size_t stream_size = 0;
|
||||||
mutable bool is_lazy = false;
|
mutable bool is_lazy = false;
|
||||||
|
mutable bool is_loaded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
@ -99,7 +99,7 @@ template <class T> class segment_impl : public segment
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
const char* get_data() const override
|
const char* get_data() const override
|
||||||
{
|
{
|
||||||
if ( is_lazy ) {
|
if ( !is_loaded ) {
|
||||||
load_data();
|
load_data();
|
||||||
}
|
}
|
||||||
return data.get();
|
return data.get();
|
||||||
@ -108,8 +108,10 @@ template <class T> class segment_impl : public segment
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void free_data() const override
|
void free_data() const override
|
||||||
{
|
{
|
||||||
data.reset( nullptr );
|
if ( is_lazy ) {
|
||||||
is_lazy = true;
|
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 ) );
|
stream.read( reinterpret_cast<char*>( &ph ), sizeof( ph ) );
|
||||||
is_offset_set = true;
|
is_offset_set = true;
|
||||||
|
|
||||||
if ( !is_lazy ) {
|
if ( !( is_lazy || is_loaded ) ) {
|
||||||
return load_data();
|
return load_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +202,6 @@ template <class T> class segment_impl : public segment
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
bool load_data() const
|
bool load_data() const
|
||||||
{
|
{
|
||||||
is_lazy = false;
|
|
||||||
if ( PT_NULL == get_type() || 0 == get_file_size() ) {
|
if ( PT_NULL == get_type() || 0 == get_file_size() ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -223,6 +224,8 @@ template <class T> class segment_impl : public segment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_loaded = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +258,7 @@ template <class T> class segment_impl : public segment
|
|||||||
size_t stream_size = 0;
|
size_t stream_size = 0;
|
||||||
bool is_offset_set = false;
|
bool is_offset_set = false;
|
||||||
mutable bool is_lazy = false;
|
mutable bool is_lazy = false;
|
||||||
|
mutable bool is_loaded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ELFIO
|
} // namespace ELFIO
|
||||||
|
@ -211,48 +211,59 @@ TEST( ELFIOTest, load32 )
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check sections
|
// Check sections
|
||||||
const section* sec = reader.sections[0];
|
const section* sec = reader.sections[0];
|
||||||
|
// sec->free_data();
|
||||||
checkSection( sec, 0, "", SHT_NULL, 0, 0, 0, 0, 0, 0, 0 );
|
checkSection( sec, 0, "", SHT_NULL, 0, 0, 0, 0, 0, 0, 0 );
|
||||||
|
|
||||||
sec = reader.sections[1];
|
sec = reader.sections[1];
|
||||||
|
// sec->free_data();
|
||||||
checkSection( sec, 1, ".interp", SHT_PROGBITS, SHF_ALLOC, 0x08048114,
|
checkSection( sec, 1, ".interp", SHT_PROGBITS, SHF_ALLOC, 0x08048114,
|
||||||
0x13, 0, 0, 1, 0 );
|
0x13, 0, 0, 1, 0 );
|
||||||
|
|
||||||
sec = reader.sections[9];
|
sec = reader.sections[9];
|
||||||
|
// sec->free_data();
|
||||||
checkSection( sec, 9, ".rel.plt", SHT_REL, SHF_ALLOC, 0x08048234, 0x18,
|
checkSection( sec, 9, ".rel.plt", SHT_REL, SHF_ALLOC, 0x08048234, 0x18,
|
||||||
4, 11, 4, 8 );
|
4, 11, 4, 8 );
|
||||||
|
|
||||||
sec = reader.sections[19];
|
sec = reader.sections[19];
|
||||||
|
// sec->free_data();
|
||||||
checkSection( sec, 19, ".dynamic", SHT_DYNAMIC, SHF_WRITE | SHF_ALLOC,
|
checkSection( sec, 19, ".dynamic", SHT_DYNAMIC, SHF_WRITE | SHF_ALLOC,
|
||||||
0x080494a0, 0xc8, 5, 0, 4, 8 );
|
0x080494a0, 0xc8, 5, 0, 4, 8 );
|
||||||
|
|
||||||
sec = reader.sections[27];
|
sec = reader.sections[27];
|
||||||
|
// sec->free_data();
|
||||||
checkSection( sec, 27, ".strtab", SHT_STRTAB, 0, 0x0, 0x259, 0, 0, 1,
|
checkSection( sec, 27, ".strtab", SHT_STRTAB, 0, 0x0, 0x259, 0, 0, 1,
|
||||||
0 );
|
0 );
|
||||||
|
|
||||||
for ( Elf_Half i = 0; i < reader.sections.size(); ++i ) {
|
for ( Elf_Half i = 0; i < reader.sections.size(); ++i ) {
|
||||||
sec = reader.sections[i];
|
sec = reader.sections[i];
|
||||||
|
// sec->free_data();
|
||||||
EXPECT_EQ( sec->get_index(), i );
|
EXPECT_EQ( sec->get_index(), i );
|
||||||
}
|
}
|
||||||
|
|
||||||
const section* sec1 = reader.sections[".strtab"];
|
const section* sec1 = reader.sections[".strtab"];
|
||||||
|
// sec1->free_data();
|
||||||
EXPECT_EQ( sec->get_index(), sec1->get_index() );
|
EXPECT_EQ( sec->get_index(), sec1->get_index() );
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check segments
|
// Check segments
|
||||||
const segment* seg = reader.segments[0];
|
const segment* seg = reader.segments[0];
|
||||||
|
seg->free_data();
|
||||||
checkSegment( seg, PT_PHDR, 0x08048034, 0x08048034, 0x000e0, 0x000e0,
|
checkSegment( seg, PT_PHDR, 0x08048034, 0x08048034, 0x000e0, 0x000e0,
|
||||||
PF_R + PF_X, 4 );
|
PF_R + PF_X, 4 );
|
||||||
|
|
||||||
seg = reader.segments[4];
|
seg = reader.segments[4];
|
||||||
|
seg->free_data();
|
||||||
checkSegment( seg, PT_DYNAMIC, 0x080494a0, 0x080494a0, 0x000c8, 0x000c8,
|
checkSegment( seg, PT_DYNAMIC, 0x080494a0, 0x080494a0, 0x000c8, 0x000c8,
|
||||||
PF_R + PF_W, 4 );
|
PF_R + PF_W, 4 );
|
||||||
|
|
||||||
seg = reader.segments[6];
|
seg = reader.segments[6];
|
||||||
|
seg->free_data();
|
||||||
checkSegment( seg, 0x6474E551, 0x0, 0x0, 0x0, 0x0, PF_R + PF_W, 4 );
|
checkSegment( seg, 0x6474E551, 0x0, 0x0, 0x0, 0x0, PF_R + PF_W, 4 );
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check symbol table
|
// Check symbol table
|
||||||
sec = reader.sections[".symtab"];
|
sec = reader.sections[".symtab"];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
const_symbol_section_accessor sr( reader, sec );
|
const_symbol_section_accessor sr( reader, sec );
|
||||||
|
|
||||||
@ -274,6 +285,7 @@ TEST( ELFIOTest, load32 )
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check relocation table
|
// Check relocation table
|
||||||
sec = reader.sections[".rel.dyn"];
|
sec = reader.sections[".rel.dyn"];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
const_relocation_section_accessor reloc( reader, sec );
|
const_relocation_section_accessor reloc( reader, sec );
|
||||||
EXPECT_EQ( reloc.get_entries_num(), 1 );
|
EXPECT_EQ( reloc.get_entries_num(), 1 );
|
||||||
@ -282,6 +294,7 @@ TEST( ELFIOTest, load32 )
|
|||||||
R_386_GLOB_DAT, 0, 0 );
|
R_386_GLOB_DAT, 0, 0 );
|
||||||
|
|
||||||
sec = reader.sections[".rel.plt"];
|
sec = reader.sections[".rel.plt"];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
const_relocation_section_accessor reloc1( reader, sec );
|
const_relocation_section_accessor reloc1( reader, sec );
|
||||||
EXPECT_EQ( reloc1.get_entries_num(), 3 );
|
EXPECT_EQ( reloc1.get_entries_num(), 3 );
|
||||||
@ -322,26 +335,30 @@ TEST( ELFIOTest, load64 )
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check sections
|
// Check sections
|
||||||
const section* sec = reader.sections[0];
|
const section* sec = reader.sections[0];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
checkSection( sec, 0, "", SHT_NULL, 0, 0, 0, 0, 0, 0, 0 );
|
checkSection( sec, 0, "", SHT_NULL, 0, 0, 0, 0, 0, 0, 0 );
|
||||||
|
|
||||||
sec = reader.sections[1];
|
sec = reader.sections[1];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
checkSection( sec, 1, ".interp", SHT_PROGBITS, SHF_ALLOC,
|
checkSection( sec, 1, ".interp", SHT_PROGBITS, SHF_ALLOC,
|
||||||
0x0000000000400200, 0x1c, 0, 0, 1, 0 );
|
0x0000000000400200, 0x1c, 0, 0, 1, 0 );
|
||||||
|
|
||||||
sec = reader.sections[9];
|
sec = reader.sections[9];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
checkSection( sec, 9, ".rela.plt", SHT_RELA, SHF_ALLOC,
|
checkSection( sec, 9, ".rela.plt", SHT_RELA, SHF_ALLOC,
|
||||||
0x0000000000400340, 0x30, 4, 11, 8, 0x18 );
|
0x0000000000400340, 0x30, 4, 11, 8, 0x18 );
|
||||||
|
|
||||||
sec = reader.sections[20];
|
sec = reader.sections[20];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
checkSection( sec, 20, ".dynamic", SHT_DYNAMIC, SHF_WRITE | SHF_ALLOC,
|
checkSection( sec, 20, ".dynamic", SHT_DYNAMIC, SHF_WRITE | SHF_ALLOC,
|
||||||
0x0000000000600698, 0x190, 5, 0, 8, 0x10 );
|
0x0000000000600698, 0x190, 5, 0, 8, 0x10 );
|
||||||
|
|
||||||
sec = reader.sections[28];
|
sec = reader.sections[28];
|
||||||
|
// sec->free_data();
|
||||||
checkSection( sec, 28, ".strtab", SHT_STRTAB, 0, 0x0, 0x23f, 0, 0, 1,
|
checkSection( sec, 28, ".strtab", SHT_STRTAB, 0, 0x0, 0x23f, 0, 0, 1,
|
||||||
0 );
|
0 );
|
||||||
|
|
||||||
@ -351,20 +368,24 @@ TEST( ELFIOTest, load64 )
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check segments
|
// Check segments
|
||||||
const segment* seg = reader.segments[0];
|
const segment* seg = reader.segments[0];
|
||||||
|
seg->free_data();
|
||||||
checkSegment( seg, PT_PHDR, 0x0000000000400040, 0x0000000000400040,
|
checkSegment( seg, PT_PHDR, 0x0000000000400040, 0x0000000000400040,
|
||||||
0x00000000000001c0, 0x00000000000001c0, PF_R + PF_X, 8 );
|
0x00000000000001c0, 0x00000000000001c0, PF_R + PF_X, 8 );
|
||||||
|
|
||||||
seg = reader.segments[2];
|
seg = reader.segments[2];
|
||||||
|
seg->free_data();
|
||||||
checkSegment( seg, PT_LOAD, 0x0000000000400000, 0x0000000000400000,
|
checkSegment( seg, PT_LOAD, 0x0000000000400000, 0x0000000000400000,
|
||||||
0x000000000000066c, 0x000000000000066c, PF_R + PF_X,
|
0x000000000000066c, 0x000000000000066c, PF_R + PF_X,
|
||||||
0x200000 );
|
0x200000 );
|
||||||
|
|
||||||
seg = reader.segments[7];
|
seg = reader.segments[7];
|
||||||
|
seg->free_data();
|
||||||
checkSegment( seg, 0x6474E551, 0x0, 0x0, 0x0, 0x0, PF_R + PF_W, 8 );
|
checkSegment( seg, 0x6474E551, 0x0, 0x0, 0x0, 0x0, PF_R + PF_W, 8 );
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check symbol table
|
// Check symbol table
|
||||||
sec = reader.sections[".symtab"];
|
sec = reader.sections[".symtab"];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
const_symbol_section_accessor sr( reader, sec );
|
const_symbol_section_accessor sr( reader, sec );
|
||||||
|
|
||||||
@ -387,6 +408,7 @@ TEST( ELFIOTest, load64 )
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check relocation table
|
// Check relocation table
|
||||||
sec = reader.sections[".rela.dyn"];
|
sec = reader.sections[".rela.dyn"];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
const_relocation_section_accessor reloc( reader, sec );
|
const_relocation_section_accessor reloc( reader, sec );
|
||||||
EXPECT_EQ( reloc.get_entries_num(), 1 );
|
EXPECT_EQ( reloc.get_entries_num(), 1 );
|
||||||
@ -407,6 +429,7 @@ TEST( ELFIOTest, load64 )
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Check note reader
|
// Check note reader
|
||||||
sec = reader.sections[".note.ABI-tag"];
|
sec = reader.sections[".note.ABI-tag"];
|
||||||
|
// sec->free_data();
|
||||||
|
|
||||||
const_note_section_accessor notes( reader, sec );
|
const_note_section_accessor notes( reader, sec );
|
||||||
EXPECT_EQ( notes.get_notes_num(), 1u );
|
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 );
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user