@@ -432,44 +432,83 @@ static uint64_t roundUp(uint64_t n, uint64_t m)
432
432
433
433
434
434
template <ElfFileParams>
435
- void ElfFile<ElfFileParamNames>::shiftFile(unsigned int extraPages, Elf_Addr startPage )
435
+ void ElfFile<ElfFileParamNames>::shiftFile(unsigned int extraPages, size_t startOffset )
436
436
{
437
- /* Move the entire contents of the file 'extraPages' pages
438
- further. */
437
+ assert (startOffset >= sizeof (Elf_Ehdr));
438
+
439
439
unsigned int oldSize = fileContents->size ();
440
+ assert (oldSize > startOffset);
441
+
442
+ /* Move the entire contents of the file after 'startOffset' by 'extraPages' pages further. */
440
443
unsigned int shift = extraPages * getPageSize ();
441
444
fileContents->resize (oldSize + shift, 0 );
442
- memmove (fileContents->data () + shift, fileContents->data (), oldSize);
443
- memset (fileContents->data () + sizeof (Elf_Ehdr) , 0 , shift - sizeof (Elf_Ehdr) );
445
+ memmove (fileContents->data () + startOffset + shift, fileContents->data () + startOffset , oldSize - startOffset );
446
+ memset (fileContents->data () + startOffset , 0 , shift);
444
447
445
448
/* Adjust the ELF header. */
446
449
wri (hdr ()->e_phoff , sizeof (Elf_Ehdr));
447
- wri (hdr ()->e_shoff , rdi (hdr ()->e_shoff ) + shift);
450
+ if (rdi (hdr ()->e_shoff ) >= startOffset)
451
+ wri (hdr ()->e_shoff , rdi (hdr ()->e_shoff ) + shift);
448
452
449
453
/* Update the offsets in the section headers. */
450
- for (int i = 1 ; i < rdi (hdr ()->e_shnum ); ++i)
451
- wri (shdrs.at (i).sh_offset , rdi (shdrs.at (i).sh_offset ) + shift);
454
+ for (int i = 1 ; i < rdi (hdr ()->e_shnum ); ++i) {
455
+ size_t sh_offset = rdi (shdrs.at (i).sh_offset );
456
+ if (sh_offset >= startOffset)
457
+ wri (shdrs.at (i).sh_offset , sh_offset + shift);
458
+ }
459
+
460
+ int splitIndex = -1 ;
461
+ size_t splitShift = 0 ;
452
462
453
463
/* Update the offsets in the program headers. */
454
464
for (int i = 0 ; i < rdi (hdr ()->e_phnum ); ++i) {
455
- wri (phdrs.at (i).p_offset , rdi (phdrs.at (i).p_offset ) + shift);
456
- if (rdi (phdrs.at (i).p_align ) != 0 &&
457
- (rdi (phdrs.at (i).p_vaddr ) - rdi (phdrs.at (i).p_offset )) % rdi (phdrs.at (i).p_align ) != 0 ) {
458
- debug (" changing alignment of program header %d from %d to %d\n " , i,
459
- rdi (phdrs.at (i).p_align ), getPageSize ());
460
- wri (phdrs.at (i).p_align , getPageSize ());
465
+ Elf_Off p_start = rdi (phdrs.at (i).p_offset );
466
+
467
+ if (p_start <= startOffset && p_start + rdi (phdrs.at (i).p_filesz ) > startOffset && rdi (phdrs.at (i).p_type ) == PT_LOAD) {
468
+ assert (splitIndex == -1 );
469
+
470
+ splitIndex = i;
471
+ splitShift = startOffset - p_start;
472
+
473
+ /* This is the load segment we're currently extending within, so we split it. */
474
+ wri (phdrs.at (i).p_offset , startOffset);
475
+ wri (phdrs.at (i).p_memsz , rdi (phdrs.at (i).p_memsz ) - splitShift);
476
+ wri (phdrs.at (i).p_filesz , rdi (phdrs.at (i).p_filesz ) - splitShift);
477
+ wri (phdrs.at (i).p_paddr , rdi (phdrs.at (i).p_paddr ) + splitShift);
478
+ wri (phdrs.at (i).p_vaddr , rdi (phdrs.at (i).p_vaddr ) + splitShift);
479
+
480
+ p_start = startOffset;
481
+ }
482
+
483
+ if (p_start >= startOffset) {
484
+ wri (phdrs.at (i).p_offset , p_start + shift);
485
+ if (rdi (phdrs.at (i).p_align ) != 0 &&
486
+ (rdi (phdrs.at (i).p_vaddr ) - rdi (phdrs.at (i).p_offset )) % rdi (phdrs.at (i).p_align ) != 0 ) {
487
+ debug (" changing alignment of program header %d from %d to %d\n " , i,
488
+ rdi (phdrs.at (i).p_align ), getPageSize ());
489
+ wri (phdrs.at (i).p_align , getPageSize ());
490
+ }
491
+ } else {
492
+ /* If we're not physically shifting, shift back virtual memory. */
493
+ if (rdi (phdrs.at (i).p_paddr ) >= shift)
494
+ wri (phdrs.at (i).p_paddr , rdi (phdrs.at (i).p_paddr ) - shift);
495
+ if (rdi (phdrs.at (i).p_vaddr ) >= shift)
496
+ wri (phdrs.at (i).p_vaddr , rdi (phdrs.at (i).p_vaddr ) - shift);
461
497
}
462
498
}
463
499
500
+ assert (splitIndex != -1 );
501
+
464
502
/* Add a segment that maps the new program/section headers and
465
503
PT_INTERP segment into memory. Otherwise glibc will choke. */
466
504
phdrs.resize (rdi (hdr ()->e_phnum ) + 1 );
467
505
wri (hdr ()->e_phnum , rdi (hdr ()->e_phnum ) + 1 );
468
506
Elf_Phdr & phdr = phdrs.at (rdi (hdr ()->e_phnum ) - 1 );
469
507
wri (phdr.p_type , PT_LOAD);
470
- wri (phdr.p_offset , 0 );
471
- wri (phdr.p_vaddr , wri (phdr.p_paddr , startPage));
472
- wri (phdr.p_filesz , wri (phdr.p_memsz , shift));
508
+ wri (phdr.p_offset , phdrs.at (splitIndex).p_offset - splitShift - shift);
509
+ wri (phdr.p_paddr , phdrs.at (splitIndex).p_paddr - splitShift - shift);
510
+ wri (phdr.p_vaddr , phdrs.at (splitIndex).p_vaddr - splitShift - shift);
511
+ wri (phdr.p_filesz , wri (phdr.p_memsz , splitShift + shift));
473
512
wri (phdr.p_flags , PF_R | PF_W);
474
513
wri (phdr.p_align , getPageSize ());
475
514
}
@@ -855,7 +894,6 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
855
894
file by the minimum number of pages and adjust internal
856
895
offsets. */
857
896
if (neededSpace > startOffset) {
858
-
859
897
/* We also need an additional program header, so adjust for that. */
860
898
neededSpace += sizeof (Elf_Phdr);
861
899
debug (" needed space is %d\n " , neededSpace);
@@ -865,10 +903,10 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
865
903
if (neededPages * getPageSize () > firstPage)
866
904
error (" virtual address space underrun!" );
867
905
906
+ shiftFile (neededPages, startOffset);
907
+
868
908
firstPage -= neededPages * getPageSize ();
869
909
startOffset += neededPages * getPageSize ();
870
-
871
- shiftFile (neededPages, firstPage);
872
910
}
873
911
874
912
0 commit comments