@@ -230,15 +230,6 @@ void elf_file::flatten(void) {
230230 }
231231 idx++;
232232 }
233-
234- idx = 0 ;
235- for (const auto &ph : ph_entries) {
236- if (ph.filez ) {
237- elf_bytes.resize (std::max (ph.offset + ph.filez , (uint32_t )elf_bytes.size ()));
238- memcpy (&elf_bytes[ph.offset ], &ph_data[idx][0 ], ph.filez );
239- }
240- idx++;
241- }
242233 if (verbose) printf (" Elf file size %zu\n " , elf_bytes.size ());
243234}
244235
@@ -260,6 +251,29 @@ void elf_file::read_sh(void) {
260251 }
261252}
262253
254+ // If there are holes between sections within segments, increase the section size to plug the hole
255+ // This is necessary to ensure the whole segment contains data defined in sections, otherwise you end up
256+ // signing/hashing/encrypting data that may not be written, as many tools write in sections not segments
257+ void elf_file::remove_sh_holes (void ) {
258+ for (int i=0 ; i+1 < sh_entries.size (); i++) {
259+ auto sh0 = &(sh_entries[i]);
260+ elf32_sh_entry sh1 = sh_entries[i+1 ];
261+ if (
262+ (sh0->type == SHT_PROGBITS && sh1.type == SHT_PROGBITS )
263+ && (sh0->size && sh1.size )
264+ && (sh0->addr + sh0->size < sh1.addr )
265+ && (segment_from_virtual_address (sh0->addr ) == segment_from_virtual_address (sh1.addr ))
266+ ) {
267+ uint32_t gap = sh1.addr - sh0->addr - sh0->size ;
268+ if (gap > sh1.addralign ) {
269+ fail (ERROR_INCOMPATIBLE , " Cannot plug gap greater than alignment - gap %d, alignment %d" , gap, sh1.addralign );
270+ }
271+ if (verbose) printf (" Section %d: Moving end from 0x%08x to 0x%08x to plug gap\n " , i, sh0->addr + sh0->size , sh1.addr );
272+ sh0->size = sh1.addr - sh0->addr ;
273+ }
274+ }
275+ }
276+
263277// Read the section data from the internal byte array into discrete sections.
264278// This is used after modifying segments but before inserting new segments
265279void elf_file::read_sh_data (void ) {
@@ -274,18 +288,6 @@ void elf_file::read_sh_data(void) {
274288 }
275289}
276290
277- void elf_file::read_ph_data (void ) {
278- int ph_idx = 0 ;
279- ph_data.resize (eh.ph_num );
280- for (const auto &ph: ph_entries) {
281- if (ph.filez ) {
282- ph_data[ph_idx].resize (ph.filez );
283- read_bytes (ph.offset , ph.filez , &ph_data[ph_idx][0 ]);
284- }
285- ph_idx++;
286- }
287- }
288-
289291const std::string elf_file::section_name (uint32_t sh_name) const {
290292 if (!eh.sh_str_index || eh.sh_str_index > eh.sh_num )
291293 return " " ;
@@ -391,9 +393,11 @@ int elf_file::read_file(std::shared_ptr<std::iostream> file) {
391393 if (!rc) {
392394 read_ph ();
393395 read_sh ();
396+
397+ // Remove any holes in the ELF file, as these cause issues when signing/hashing/encrypting
398+ remove_sh_holes ();
394399 }
395400 read_sh_data ();
396- read_ph_data ();
397401 }
398402 catch (const std::ios_base::failure &e) {
399403 std::cerr << " Failed to read elf file" << std::endl;
@@ -440,7 +444,6 @@ void elf_file::content(const elf32_ph_entry &ph, const std::vector<uint8_t> &con
440444 if (verbose) printf (" Update segment content offset %x content size %zx physical size %x\n " , ph.offset , content.size (), ph.filez );
441445 memcpy (&elf_bytes[ph.offset ], &content[0 ], std::min (content.size (), (size_t ) ph.filez ));
442446 read_sh_data (); // Extract the sections after modifying the content
443- read_ph_data ();
444447}
445448
446449void elf_file::content (const elf32_sh_entry &sh, const std::vector<uint8_t > &content) {
@@ -449,7 +452,6 @@ void elf_file::content(const elf32_sh_entry &sh, const std::vector<uint8_t> &con
449452 if (verbose) printf (" Update section content offset %x content size %zx section size %x\n " , sh.offset , content.size (), sh.size );
450453 memcpy (&elf_bytes[sh.offset ], &content[0 ], std::min (content.size (), (size_t ) sh.size ));
451454 read_sh_data (); // Extract the sections after modifying the content
452- read_ph_data ();
453455}
454456
455457const elf32_ph_entry* elf_file::segment_from_physical_address (uint32_t paddr) {
@@ -527,7 +529,6 @@ const elf32_ph_entry& elf_file::append_segment(uint32_t vaddr, uint32_t paddr, u
527529 sh_entries.push_back (sh);
528530 sh_data.push_back (std::vector<uint8_t >(size));
529531 ph_entries.back ().offset = sh.offset ;
530- ph_data.push_back (std::vector<uint8_t >(size));
531532
532533 eh.sh_offset = sh.offset + sh.size ;
533534 eh.sh_num ++;
0 commit comments