@@ -251,7 +251,33 @@ void elf_file::read_sh(void) {
251251 }
252252}
253253
254- // If there are holes between sections within segments, increase the section size to plug the hole
254+ // If there are holes between segments, increase the segment size to plug the hole
255+ // This is necessary to ensure that segments are contiguous, which is required for encrypting,
256+ // but this is not necessary for signing/hashing
257+ void elf_file::remove_ph_holes (void ) {
258+ for (int i=0 ; i+1 < ph_entries.size (); i++) {
259+ auto ph0 = &(ph_entries[i]);
260+ elf32_ph_entry ph1 = ph_entries[i+1 ];
261+ if (
262+ (ph0->type == PT_LOAD && ph1.type == PT_LOAD)
263+ && (ph0->filez && ph1.filez )
264+ && (ph0->paddr + ph0->filez < ph1.paddr )
265+ ) {
266+ uint32_t gap = ph1.paddr - ph0->paddr - ph0->filez ;
267+ if (gap > ph1.align ) {
268+ fail (ERROR_INCOMPATIBLE, " Segment %d: Cannot plug gap greater than alignment - gap %d, alignment %d" , i, gap, ph1.align );
269+ }
270+ if (ph0->offset + ph0->filez + gap > ph1.offset ) {
271+ fail (ERROR_INCOMPATIBLE, " Segment %d: Cannot plug gap without space in file - gap %d" , i, gap);
272+ }
273+ if (verbose) printf (" Segment %d: Moving end from 0x%08x to 0x%08x to plug gap\n " , i, ph0->paddr + ph0->filez , ph1.paddr );
274+ ph0->filez = ph1.paddr - ph0->paddr ;
275+ ph0->memsz = ph0->filez ;
276+ }
277+ }
278+ }
279+
280+ // If there are holes within segments, increase the section size to plug the hole
255281// This is necessary to ensure the whole segment contains data defined in sections, otherwise you end up
256282// signing/hashing/encrypting data that may not be written, as many tools write in sections not segments
257283void elf_file::remove_sh_holes (void ) {
@@ -273,11 +299,31 @@ void elf_file::remove_sh_holes(void) {
273299 if (verbose) printf (" Section %d: Moving end from 0x%08x to 0x%08x to plug gap\n " , i, sh0->addr + sh0->size , sh1.addr );
274300 sh0->size = sh1.addr - sh0->addr ;
275301 found_hole = true ;
302+ } else if (
303+ (sh0->type == SHT_PROGBITS)
304+ && (segment_from_section (*sh0) != segment_from_section (sh1))
305+ && segment_from_section (*sh0) != NULL
306+ && (sh0->offset + sh0->size < segment_from_section (*sh0)->offset + segment_from_section (*sh0)->filez )
307+ ) {
308+ const elf32_ph_entry *seg = segment_from_section (*sh0);
309+ uint32_t gap = seg->offset + seg->filez - sh0->offset - sh0->size ;
310+ if (verbose) printf (" Section %d: Moving end from 0x%08x to 0x%08x to plug gap at end of segment\n " , i, sh0->addr + sh0->size , seg->offset + seg->filez );
311+ sh0->size = seg->offset + seg->filez - sh0->offset ;
312+ found_hole = true ;
276313 }
277314 }
278315 if (found_hole) read_sh_data ();
279316}
280317
318+ void elf_file::remove_empty_ph_entries (void ) {
319+ for (int i = 0 ; i < ph_entries.size (); i++) {
320+ if (ph_entries[i].filez == 0 ) {
321+ ph_entries.erase (ph_entries.begin () + i);
322+ eh.ph_num --; i--;
323+ }
324+ }
325+ }
326+
281327// Read the section data from the internal byte array into discrete sections.
282328// This is used after modifying segments but before inserting new segments
283329void elf_file::read_sh_data (void ) {
@@ -373,6 +419,8 @@ void elf_file::dump(void) const {
373419
374420void elf_file::move_all (int dist) {
375421 if (verbose) printf (" Incrementing all paddr by %d\n " , dist);
422+ // Remove empty ph entries, as they will likely be moved to invalid addresses
423+ remove_empty_ph_entries ();
376424 for (auto &ph: ph_entries) {
377425 ph.paddr += dist;
378426 }
0 commit comments