mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2024-11-22 04:39:17 +01:00
Remove all save functions from ELFIO. We don't need them anyway
This commit is contained in:
parent
c9ccf0f657
commit
8367e0e32c
@ -197,54 +197,6 @@ class elfio
|
|||||||
return is_still_good;
|
return is_still_good;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool save( const std::string& file_name )
|
|
||||||
{
|
|
||||||
std::ofstream stream;
|
|
||||||
stream.open( file_name.c_str(), std::ios::out | std::ios::binary );
|
|
||||||
if ( !stream ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return save( stream );
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool save( std::ostream& stream )
|
|
||||||
{
|
|
||||||
if ( !stream || header == nullptr ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define layout specific header fields
|
|
||||||
// The position of the segment table is fixed after the header.
|
|
||||||
// The position of the section table is variable and needs to be fixed
|
|
||||||
// before saving.
|
|
||||||
header->set_segments_num( segments.size() );
|
|
||||||
header->set_segments_offset(
|
|
||||||
segments.size() > 0 ? header->get_header_size() : 0 );
|
|
||||||
header->set_sections_num( sections.size() );
|
|
||||||
header->set_sections_offset( 0 );
|
|
||||||
|
|
||||||
// Layout the first section right after the segment table
|
|
||||||
current_file_pos =
|
|
||||||
header->get_header_size() +
|
|
||||||
header->get_segment_entry_size() *
|
|
||||||
static_cast<Elf_Xword>( header->get_segments_num() );
|
|
||||||
|
|
||||||
calc_segment_alignment();
|
|
||||||
|
|
||||||
bool is_still_good = layout_segments_and_their_sections();
|
|
||||||
is_still_good = is_still_good && layout_sections_without_segments();
|
|
||||||
is_still_good = is_still_good && layout_section_table();
|
|
||||||
|
|
||||||
is_still_good = is_still_good && save_header( stream );
|
|
||||||
is_still_good = is_still_good && save_sections( stream );
|
|
||||||
is_still_good = is_still_good && save_segments( stream );
|
|
||||||
|
|
||||||
return is_still_good;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// ELF header access functions
|
// ELF header access functions
|
||||||
ELFIO_HEADER_ACCESS_GET( unsigned char, class );
|
ELFIO_HEADER_ACCESS_GET( unsigned char, class );
|
||||||
@ -268,107 +220,6 @@ class elfio
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
const endianess_convertor& get_convertor() const { return convertor; }
|
const endianess_convertor& get_convertor() const { return convertor; }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
Elf_Xword get_default_entry_size( Elf_Word section_type ) const
|
|
||||||
{
|
|
||||||
switch ( section_type ) {
|
|
||||||
case SHT_RELA:
|
|
||||||
if ( header->get_class() == ELFCLASS64 ) {
|
|
||||||
return sizeof( Elf64_Rela );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return sizeof( Elf32_Rela );
|
|
||||||
}
|
|
||||||
case SHT_REL:
|
|
||||||
if ( header->get_class() == ELFCLASS64 ) {
|
|
||||||
return sizeof( Elf64_Rel );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return sizeof( Elf32_Rel );
|
|
||||||
}
|
|
||||||
case SHT_SYMTAB:
|
|
||||||
if ( header->get_class() == ELFCLASS64 ) {
|
|
||||||
return sizeof( Elf64_Sym );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return sizeof( Elf32_Sym );
|
|
||||||
}
|
|
||||||
case SHT_DYNAMIC:
|
|
||||||
if ( header->get_class() == ELFCLASS64 ) {
|
|
||||||
return sizeof( Elf64_Dyn );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return sizeof( Elf32_Dyn );
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
//! returns an empty string if no problems are detected,
|
|
||||||
//! or a string containing an error message if problems are found,
|
|
||||||
//! with one error per line.
|
|
||||||
std::string validate() const
|
|
||||||
{
|
|
||||||
// clang-format off
|
|
||||||
|
|
||||||
std::string errors;
|
|
||||||
// Check for overlapping sections in the file
|
|
||||||
// This is explicitly forbidden by ELF specification
|
|
||||||
for ( int i = 0; i < sections.size(); ++i) {
|
|
||||||
for ( int j = i+1; j < sections.size(); ++j ) {
|
|
||||||
const section* a = sections[i];
|
|
||||||
const section* b = sections[j];
|
|
||||||
if ( ( ( a->get_type() & SHT_NOBITS) == 0 )
|
|
||||||
&& ( ( b->get_type() & SHT_NOBITS) == 0 )
|
|
||||||
&& ( a->get_size() > 0 )
|
|
||||||
&& ( b->get_size() > 0 )
|
|
||||||
&& ( a->get_offset() > 0 )
|
|
||||||
&& ( b->get_offset() > 0 )
|
|
||||||
&& ( is_offset_in_section( a->get_offset(), b )
|
|
||||||
|| is_offset_in_section( a->get_offset()+a->get_size()-1, b )
|
|
||||||
|| is_offset_in_section( b->get_offset(), a )
|
|
||||||
|| is_offset_in_section( b->get_offset()+b->get_size()-1, a ) ) ) {
|
|
||||||
errors += "Sections " + a->get_name() + " and " + b->get_name() + " overlap in file\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// Check for conflicting section / program header tables, where
|
|
||||||
// the same offset has different vaddresses in section table and
|
|
||||||
// program header table.
|
|
||||||
// This doesn't seem to be explicitly forbidden by ELF specification,
|
|
||||||
// but:
|
|
||||||
// - it doesn't make any sense
|
|
||||||
// - ELFIO relies on this being consistent when writing ELF files,
|
|
||||||
// since offsets are re-calculated from vaddress
|
|
||||||
for ( int h = 0; h < segments.size(); ++h ) {
|
|
||||||
const segment* seg = segments[h];
|
|
||||||
const section* sec =
|
|
||||||
find_prog_section_for_offset( seg->get_offset() );
|
|
||||||
if ( seg->get_type() == PT_LOAD && seg->get_file_size() > 0 &&
|
|
||||||
sec != nullptr ) {
|
|
||||||
Elf64_Addr sec_addr =
|
|
||||||
get_virtual_addr( seg->get_offset(), sec );
|
|
||||||
if ( sec_addr != seg->get_virtual_address() ) {
|
|
||||||
errors += "Virtual address of segment " +
|
|
||||||
std::to_string( h ) + " (" +
|
|
||||||
to_hex_string( seg->get_virtual_address() ) +
|
|
||||||
")" + " conflicts with address of section " +
|
|
||||||
sec->get_name() + " (" +
|
|
||||||
to_hex_string( sec_addr ) + ")" + " at offset " +
|
|
||||||
to_hex_string( seg->get_offset() ) + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// more checks to be added here...
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
static bool is_offset_in_section( Elf64_Off offset, const section* sec )
|
static bool is_offset_in_section( Elf64_Off offset, const section* sec )
|
||||||
@ -377,24 +228,6 @@ class elfio
|
|||||||
( offset < ( sec->get_offset() + sec->get_size() ) );
|
( offset < ( sec->get_offset() + sec->get_size() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
static Elf64_Addr get_virtual_addr( Elf64_Off offset, const section* sec )
|
|
||||||
{
|
|
||||||
return sec->get_address() + offset - sec->get_offset();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
const section* find_prog_section_for_offset( Elf64_Off offset ) const
|
|
||||||
{
|
|
||||||
for ( const auto& sec : sections ) {
|
|
||||||
if ( sec->get_type() == SHT_PROGBITS &&
|
|
||||||
is_offset_in_section( offset, sec.get() ) ) {
|
|
||||||
return sec.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
std::unique_ptr<elf_header> create_header( unsigned char file_class,
|
std::unique_ptr<elf_header> create_header( unsigned char file_class,
|
||||||
unsigned char encoding )
|
unsigned char encoding )
|
||||||
@ -613,334 +446,8 @@ class elfio
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool save_header( std::ostream& stream ) const
|
|
||||||
{
|
|
||||||
return header->save( stream );
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool save_sections( std::ostream& stream ) const
|
|
||||||
{
|
|
||||||
for ( const auto& sec : sections_ ) {
|
|
||||||
std::streampos headerPosition =
|
|
||||||
static_cast<std::streamoff>( header->get_sections_offset() ) +
|
|
||||||
static_cast<std::streampos>(
|
|
||||||
header->get_section_entry_size() ) *
|
|
||||||
sec->get_index();
|
|
||||||
|
|
||||||
sec->save( stream, headerPosition, sec->get_offset() );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool save_segments( std::ostream& stream ) const
|
|
||||||
{
|
|
||||||
for ( const auto& seg : segments_ ) {
|
|
||||||
std::streampos headerPosition =
|
|
||||||
static_cast<std::streamoff>( header->get_segments_offset() ) +
|
|
||||||
static_cast<std::streampos>(
|
|
||||||
header->get_segment_entry_size() ) *
|
|
||||||
seg->get_index();
|
|
||||||
|
|
||||||
seg->save( stream, headerPosition, seg->get_offset() );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool is_section_without_segment( unsigned int section_index ) const
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
for ( unsigned int j = 0; !found && ( j < segments.size() ); ++j ) {
|
|
||||||
for ( Elf_Half k = 0;
|
|
||||||
!found && ( k < segments[j]->get_sections_num() ); ++k ) {
|
|
||||||
found = segments[j]->get_section_index_at( k ) == section_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return !found;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
static bool is_subsequence_of( const segment* seg1, const segment* seg2 )
|
|
||||||
{
|
|
||||||
// Return 'true' if sections of seg1 are a subset of sections in seg2
|
|
||||||
const std::vector<Elf_Half>& sections1 = seg1->get_sections();
|
|
||||||
const std::vector<Elf_Half>& sections2 = seg2->get_sections();
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
if ( sections1.size() < sections2.size() ) {
|
|
||||||
found = std::includes( sections2.begin(), sections2.end(),
|
|
||||||
sections1.begin(), sections1.end() );
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
std::vector<segment*> get_ordered_segments() const
|
|
||||||
{
|
|
||||||
std::vector<segment*> res;
|
|
||||||
std::deque<segment*> worklist;
|
|
||||||
|
|
||||||
res.reserve( segments.size() );
|
|
||||||
for ( const auto& seg : segments ) {
|
|
||||||
worklist.emplace_back( seg.get() );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bring the segments which start at address 0 to the front
|
|
||||||
size_t nextSlot = 0;
|
|
||||||
for ( size_t i = 0; i < worklist.size(); ++i ) {
|
|
||||||
if ( i != nextSlot && worklist[i]->is_offset_initialized() &&
|
|
||||||
worklist[i]->get_offset() == 0 ) {
|
|
||||||
if ( worklist[nextSlot]->get_offset() == 0 ) {
|
|
||||||
++nextSlot;
|
|
||||||
}
|
|
||||||
std::swap( worklist[i], worklist[nextSlot] );
|
|
||||||
++nextSlot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( !worklist.empty() ) {
|
|
||||||
segment* seg = worklist.front();
|
|
||||||
worklist.pop_front();
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
for ( ; i < worklist.size(); ++i ) {
|
|
||||||
if ( is_subsequence_of( seg, worklist[i] ) ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( i < worklist.size() ) {
|
|
||||||
worklist.emplace_back( seg );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res.emplace_back( seg );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool layout_sections_without_segments()
|
|
||||||
{
|
|
||||||
for ( unsigned int i = 0; i < sections_.size(); ++i ) {
|
|
||||||
if ( is_section_without_segment( i ) ) {
|
|
||||||
const auto& sec = sections_[i];
|
|
||||||
|
|
||||||
Elf_Xword section_align = sec->get_addr_align();
|
|
||||||
if ( section_align > 1 &&
|
|
||||||
current_file_pos % section_align != 0 ) {
|
|
||||||
current_file_pos +=
|
|
||||||
section_align - current_file_pos % section_align;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( 0 != sec->get_index() ) {
|
|
||||||
sec->set_offset( current_file_pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( SHT_NOBITS != sec->get_type() &&
|
|
||||||
SHT_NULL != sec->get_type() ) {
|
|
||||||
current_file_pos += sec->get_size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void calc_segment_alignment() const
|
|
||||||
{
|
|
||||||
for ( const auto& seg : segments_ ) {
|
|
||||||
for ( Elf_Half i = 0; i < seg->get_sections_num(); ++i ) {
|
|
||||||
const auto& sect = sections_[seg->get_section_index_at( i )];
|
|
||||||
if ( sect->get_addr_align() > seg->get_align() ) {
|
|
||||||
seg->set_align( sect->get_addr_align() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool layout_segments_and_their_sections()
|
|
||||||
{
|
|
||||||
std::vector<segment*> worklist;
|
|
||||||
std::vector<bool> section_generated( sections.size(), false );
|
|
||||||
|
|
||||||
// Get segments in a order in where segments which contain a
|
|
||||||
// sub sequence of other segments are located at the end
|
|
||||||
worklist = get_ordered_segments();
|
|
||||||
|
|
||||||
for ( auto* seg : worklist ) {
|
|
||||||
Elf_Xword segment_memory = 0;
|
|
||||||
Elf_Xword segment_filesize = 0;
|
|
||||||
Elf_Xword seg_start_pos = current_file_pos;
|
|
||||||
// Special case: PHDR segment
|
|
||||||
// This segment contains the program headers but no sections
|
|
||||||
if ( seg->get_type() == PT_PHDR && seg->get_sections_num() == 0 ) {
|
|
||||||
seg_start_pos = header->get_segments_offset();
|
|
||||||
segment_memory = segment_filesize =
|
|
||||||
header->get_segment_entry_size() *
|
|
||||||
static_cast<Elf_Xword>( header->get_segments_num() );
|
|
||||||
}
|
|
||||||
// Special case:
|
|
||||||
else if ( seg->is_offset_initialized() && seg->get_offset() == 0 ) {
|
|
||||||
seg_start_pos = 0;
|
|
||||||
if ( seg->get_sections_num() > 0 ) {
|
|
||||||
segment_memory = segment_filesize = current_file_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// New segments with not generated sections
|
|
||||||
// have to be aligned
|
|
||||||
else if ( seg->get_sections_num() > 0 &&
|
|
||||||
!section_generated[seg->get_section_index_at( 0 )] ) {
|
|
||||||
Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1;
|
|
||||||
Elf64_Off cur_page_alignment = current_file_pos % align;
|
|
||||||
Elf64_Off req_page_alignment =
|
|
||||||
seg->get_virtual_address() % align;
|
|
||||||
Elf64_Off error = req_page_alignment - cur_page_alignment;
|
|
||||||
|
|
||||||
current_file_pos += ( seg->get_align() + error ) % align;
|
|
||||||
seg_start_pos = current_file_pos;
|
|
||||||
}
|
|
||||||
else if ( seg->get_sections_num() > 0 ) {
|
|
||||||
seg_start_pos =
|
|
||||||
sections[seg->get_section_index_at( 0 )]->get_offset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write segment's data
|
|
||||||
if ( !write_segment_data( seg, section_generated, segment_memory,
|
|
||||||
segment_filesize, seg_start_pos ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg->set_file_size( segment_filesize );
|
|
||||||
|
|
||||||
// If we already have a memory size from loading an elf file (value > 0),
|
|
||||||
// it must not shrink!
|
|
||||||
// Memory size may be bigger than file size and it is the loader's job to do something
|
|
||||||
// with the surplus bytes in memory, like initializing them with a defined value.
|
|
||||||
if ( seg->get_memory_size() < segment_memory ) {
|
|
||||||
seg->set_memory_size( segment_memory );
|
|
||||||
}
|
|
||||||
|
|
||||||
seg->set_offset( seg_start_pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool layout_section_table()
|
|
||||||
{
|
|
||||||
// Simply place the section table at the end for now
|
|
||||||
Elf64_Off alignmentError = current_file_pos % 4;
|
|
||||||
current_file_pos += ( 4 - alignmentError ) % 4;
|
|
||||||
header->set_sections_offset( current_file_pos );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool write_segment_data( const segment* seg,
|
|
||||||
std::vector<bool>& section_generated,
|
|
||||||
Elf_Xword& segment_memory,
|
|
||||||
Elf_Xword& segment_filesize,
|
|
||||||
const Elf_Xword& seg_start_pos )
|
|
||||||
{
|
|
||||||
for ( Elf_Half j = 0; j < seg->get_sections_num(); ++j ) {
|
|
||||||
Elf_Half index = seg->get_section_index_at( j );
|
|
||||||
|
|
||||||
section* sec = sections[index];
|
|
||||||
|
|
||||||
// The NULL section is always generated
|
|
||||||
if ( SHT_NULL == sec->get_type() ) {
|
|
||||||
section_generated[index] = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf_Xword section_align = 0;
|
|
||||||
// Fix up the alignment
|
|
||||||
if ( !section_generated[index] && sec->is_address_initialized() &&
|
|
||||||
SHT_NOBITS != sec->get_type() && SHT_NULL != sec->get_type() &&
|
|
||||||
0 != sec->get_size() ) {
|
|
||||||
// Align the sections based on the virtual addresses
|
|
||||||
// when possible (this is what matters for execution)
|
|
||||||
Elf64_Off req_offset =
|
|
||||||
sec->get_address() - seg->get_virtual_address();
|
|
||||||
Elf64_Off cur_offset = current_file_pos - seg_start_pos;
|
|
||||||
if ( req_offset < cur_offset ) {
|
|
||||||
// something has gone awfully wrong, abort!
|
|
||||||
// section_align would turn out negative, seeking backwards and overwriting previous data
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
section_align = req_offset - cur_offset;
|
|
||||||
}
|
|
||||||
else if ( !section_generated[index] &&
|
|
||||||
!sec->is_address_initialized() ) {
|
|
||||||
// If no address has been specified then only the section
|
|
||||||
// alignment constraint has to be matched
|
|
||||||
Elf_Xword align = sec->get_addr_align();
|
|
||||||
if ( align == 0 ) {
|
|
||||||
align = 1;
|
|
||||||
}
|
|
||||||
Elf64_Off error = current_file_pos % align;
|
|
||||||
section_align = ( align - error ) % align;
|
|
||||||
}
|
|
||||||
else if ( section_generated[index] ) {
|
|
||||||
// Alignment for already generated sections
|
|
||||||
section_align =
|
|
||||||
sec->get_offset() - seg_start_pos - segment_filesize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the segment file and memory sizes
|
|
||||||
// Special case .tbss section (NOBITS) in non TLS segment
|
|
||||||
if ( ( ( sec->get_flags() & SHF_ALLOC ) == SHF_ALLOC ) &&
|
|
||||||
!( ( ( sec->get_flags() & SHF_TLS ) == SHF_TLS ) &&
|
|
||||||
( seg->get_type() != PT_TLS ) &&
|
|
||||||
( SHT_NOBITS == sec->get_type() ) ) ) {
|
|
||||||
segment_memory += sec->get_size() + section_align;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( SHT_NOBITS != sec->get_type() ) {
|
|
||||||
segment_filesize += sec->get_size() + section_align;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing to be done when generating nested segments
|
|
||||||
if ( section_generated[index] ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_file_pos += section_align;
|
|
||||||
|
|
||||||
// Set the section addresses when missing
|
|
||||||
if ( !sec->is_address_initialized() ) {
|
|
||||||
sec->set_address( seg->get_virtual_address() +
|
|
||||||
current_file_pos - seg_start_pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( 0 != sec->get_index() ) {
|
|
||||||
sec->set_offset( current_file_pos );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( SHT_NOBITS != sec->get_type() ) {
|
|
||||||
current_file_pos += sec->get_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
section_generated[index] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
public:
|
public:
|
||||||
friend class Sections;
|
|
||||||
class Sections
|
class Sections
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -33,7 +33,6 @@ class elf_header
|
|||||||
virtual ~elf_header() = default;
|
virtual ~elf_header() = default;
|
||||||
|
|
||||||
virtual bool load( std::istream& stream ) = 0;
|
virtual bool load( std::istream& stream ) = 0;
|
||||||
virtual bool save( std::ostream& stream ) const = 0;
|
|
||||||
|
|
||||||
// ELF header functions
|
// ELF header functions
|
||||||
ELFIO_GET_ACCESS_DECL( unsigned char, class );
|
ELFIO_GET_ACCESS_DECL( unsigned char, class );
|
||||||
@ -108,16 +107,6 @@ template <class T> class elf_header_impl : public elf_header
|
|||||||
return ( stream.gcount() == sizeof( header ) );
|
return ( stream.gcount() == sizeof( header ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
bool save( std::ostream& stream ) const override
|
|
||||||
{
|
|
||||||
stream.seekp( ( *translator )[0] );
|
|
||||||
stream.write( reinterpret_cast<const char*>( &header ),
|
|
||||||
sizeof( header ) );
|
|
||||||
|
|
||||||
return stream.good();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// ELF header functions
|
// ELF header functions
|
||||||
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
|
ELFIO_GET_ACCESS( unsigned char, class, header.e_ident[EI_CLASS] );
|
||||||
|
@ -68,9 +68,6 @@ class section
|
|||||||
virtual bool load( std::istream& stream,
|
virtual bool load( std::istream& stream,
|
||||||
std::streampos header_offset,
|
std::streampos header_offset,
|
||||||
bool is_lazy ) = 0;
|
bool is_lazy ) = 0;
|
||||||
virtual void save( std::ostream& stream,
|
|
||||||
std::streampos header_offset,
|
|
||||||
std::streampos data_offset ) = 0;
|
|
||||||
virtual bool is_address_initialized() const = 0;
|
virtual bool is_address_initialized() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -301,51 +298,9 @@ template <class T> class section_impl : public section
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void save( std::ostream& stream,
|
|
||||||
std::streampos header_offset,
|
|
||||||
std::streampos data_offset ) override
|
|
||||||
{
|
|
||||||
if ( 0 != get_index() ) {
|
|
||||||
header.sh_offset = decltype( header.sh_offset )( data_offset );
|
|
||||||
header.sh_offset = ( *convertor )( header.sh_offset );
|
|
||||||
}
|
|
||||||
|
|
||||||
save_header( stream, header_offset );
|
|
||||||
if ( get_type() != SHT_NOBITS && get_type() != SHT_NULL &&
|
|
||||||
get_size() != 0 && data != nullptr ) {
|
|
||||||
save_data( stream, data_offset );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
//------------------------------------------------------------------------------
|
private:
|
||||||
void save_header( std::ostream& stream, std::streampos header_offset ) const
|
|
||||||
{
|
|
||||||
adjust_stream_size( stream, header_offset );
|
|
||||||
stream.write( reinterpret_cast<const char*>( &header ),
|
|
||||||
sizeof( header ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void save_data( std::ostream& stream, std::streampos data_offset )
|
|
||||||
{
|
|
||||||
adjust_stream_size( stream, data_offset );
|
|
||||||
|
|
||||||
if ( ( ( get_flags() & SHF_COMPRESSED ) ||
|
|
||||||
( get_flags() & SHF_RPX_DEFLATE ) ) &&
|
|
||||||
compression != nullptr ) {
|
|
||||||
Elf_Xword decompressed_size = get_size();
|
|
||||||
Elf_Xword compressed_size = 0;
|
|
||||||
auto compressed_ptr = compression->deflate(
|
|
||||||
data.get(), convertor, decompressed_size, compressed_size );
|
|
||||||
stream.write( compressed_ptr.get(), compressed_size );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stream.write( get_data(), get_size() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
|
@ -65,9 +65,6 @@ class segment
|
|||||||
virtual bool load( std::istream& stream,
|
virtual bool load( std::istream& stream,
|
||||||
std::streampos header_offset,
|
std::streampos header_offset,
|
||||||
bool is_lazy ) = 0;
|
bool is_lazy ) = 0;
|
||||||
virtual void save( std::ostream& stream,
|
|
||||||
std::streampos header_offset,
|
|
||||||
std::streampos data_offset ) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -218,17 +215,6 @@ template <class T> class segment_impl : public segment
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
void save( std::ostream& stream,
|
|
||||||
std::streampos header_offset,
|
|
||||||
std::streampos data_offset ) override
|
|
||||||
{
|
|
||||||
ph.p_offset = decltype( ph.p_offset )( data_offset );
|
|
||||||
ph.p_offset = ( *convertor )( ph.p_offset );
|
|
||||||
adjust_stream_size( stream, header_offset );
|
|
||||||
stream.write( reinterpret_cast<const char*>( &ph ), sizeof( ph ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
size_t get_stream_size() const { return stream_size; }
|
size_t get_stream_size() const { return stream_size; }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user