Segment align updated when saving, not loading

After loading, the data model in memory should resemble the original ELF file as closely as possible,
so that ELF viewers based on elfio will print out the original values, not the calculated ones.
This commit is contained in:
Martin Bickel 2017-02-17 17:40:07 +01:00 committed by Serge Lamikhov-Center
parent 6c19078803
commit fe78d06e81

View File

@ -170,6 +170,8 @@ class elfio
current_file_pos = header->get_header_size() + current_file_pos = header->get_header_size() +
header->get_segment_entry_size() * header->get_segments_num(); header->get_segment_entry_size() * header->get_segments_num();
calc_segment_alignment();
is_still_good = layout_segments_and_their_sections(); 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_sections_without_segments();
is_still_good = is_still_good && layout_section_table(); is_still_good = is_still_good && layout_section_table();
@ -468,8 +470,9 @@ class elfio
if( psec->get_flags() & SHF_ALLOC if( psec->get_flags() & SHF_ALLOC
? is_sect_in_seg( psec->get_address(), psec->get_size(), segVBaseAddr, segVEndAddr ) ? is_sect_in_seg( psec->get_address(), psec->get_size(), segVBaseAddr, segVEndAddr )
: is_sect_in_seg( psec->get_offset(), psec->get_size(), segBaseOffset, segEndOffset )) { : is_sect_in_seg( psec->get_offset(), psec->get_size(), segBaseOffset, segEndOffset )) {
seg->add_section_index( psec->get_index(), // Alignment of segment shall not be updated, to preserve original value
psec->get_addr_align() ); // It will be re-calculated on saving.
seg->add_section_index( psec->get_index(), 0 );
} }
} }
@ -615,6 +618,20 @@ class elfio
} }
//------------------------------------------------------------------------------
void calc_segment_alignment( )
{
for( std::vector<segment*>::iterator s = segments_.begin(); s != segments_.end(); ++s ) {
segment* seg = *s;
for ( int i = 0; i < seg->get_sections_num(); ++i ) {
section* 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( ) bool layout_segments_and_their_sections( )
{ {
@ -651,11 +668,12 @@ class elfio
// have to be aligned // have to be aligned
else if ( seg->get_sections_num() else if ( seg->get_sections_num()
&& !section_generated[seg->get_section_index_at( 0 )] ) { && !section_generated[seg->get_section_index_at( 0 )] ) {
Elf64_Off cur_page_alignment = current_file_pos % seg->get_align(); Elf_Xword align = seg->get_align() > 0 ? seg->get_align() : 1;
Elf64_Off req_page_alignment = seg->get_virtual_address() % seg->get_align(); 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; Elf64_Off error = req_page_alignment - cur_page_alignment;
current_file_pos += ( seg->get_align() + error ) % seg->get_align(); current_file_pos += ( seg->get_align() + error ) % align;
seg_start_pos = current_file_pos; seg_start_pos = current_file_pos;
} }
else if ( seg->get_sections_num() ) { else if ( seg->get_sections_num() ) {