@@ -3887,6 +3887,43 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
38873887
38883888void RewriteInstance::mapAllocatableSections (
38893889 BOLTLinker::SectionMapper MapSection) {
3890+
3891+ if (opts::UseOldText || opts::StrictMode) {
3892+ auto tryRewriteSection = [&](BinarySection &OldSection,
3893+ BinarySection &NewSection) {
3894+ if (OldSection.getSize () < NewSection.getOutputSize ())
3895+ return ;
3896+
3897+ BC->outs () << " BOLT-INFO: rewriting " << OldSection.getName ()
3898+ << " in-place\n " ;
3899+
3900+ NewSection.setOutputAddress (OldSection.getAddress ());
3901+ NewSection.setOutputFileOffset (OldSection.getInputFileOffset ());
3902+ MapSection (NewSection, OldSection.getAddress ());
3903+
3904+ // Pad contents with zeros.
3905+ NewSection.addPadding (OldSection.getSize () - NewSection.getOutputSize ());
3906+
3907+ // Prevent the original section name from appearing in the section header
3908+ // table.
3909+ OldSection.setAnonymous (true );
3910+ };
3911+
3912+ if (EHFrameSection) {
3913+ BinarySection *NewEHFrameSection =
3914+ getSection (getNewSecPrefix () + getEHFrameSectionName ());
3915+ assert (NewEHFrameSection && " New contents expected for .eh_frame" );
3916+ tryRewriteSection (*EHFrameSection, *NewEHFrameSection);
3917+ }
3918+ BinarySection *EHSection = getSection (" .gcc_except_table" );
3919+ BinarySection *NewEHSection =
3920+ getSection (getNewSecPrefix () + " .gcc_except_table" );
3921+ if (EHSection) {
3922+ assert (NewEHSection && " New contents expected for .gcc_except_table" );
3923+ tryRewriteSection (*EHSection, *NewEHSection);
3924+ }
3925+ }
3926+
38903927 // Allocate read-only sections first, then writable sections.
38913928 enum : uint8_t { ST_READONLY, ST_READWRITE };
38923929 for (uint8_t SType = ST_READONLY; SType <= ST_READWRITE; ++SType) {
@@ -4164,7 +4201,6 @@ void RewriteInstance::rewriteNoteSections() {
41644201 // New section size.
41654202 uint64_t Size = 0 ;
41664203 bool DataWritten = false ;
4167- uint8_t *SectionData = nullptr ;
41684204 // Copy over section contents unless it's one of the sections we overwrite.
41694205 if (!willOverwriteSection (SectionName)) {
41704206 Size = Section.sh_size ;
@@ -4196,12 +4232,7 @@ void RewriteInstance::rewriteNoteSections() {
41964232 if (BSec->getAllocAddress ()) {
41974233 assert (!DataWritten && " Writing section twice." );
41984234 (void )DataWritten;
4199- SectionData = BSec->getOutputData ();
4200-
4201- LLVM_DEBUG (dbgs () << " BOLT-DEBUG: " << (Size ? " appending" : " writing" )
4202- << " contents to section " << SectionName << ' \n ' );
4203- OS.write (reinterpret_cast <char *>(SectionData), BSec->getOutputSize ());
4204- Size += BSec->getOutputSize ();
4235+ Size += BSec->write (OS);
42054236 }
42064237
42074238 BSec->setOutputFileOffset (NextAvailableOffset);
@@ -4232,8 +4263,7 @@ void RewriteInstance::rewriteNoteSections() {
42324263 << " of size " << Section.getOutputSize () << " at offset 0x"
42334264 << Twine::utohexstr (Section.getOutputFileOffset ()) << ' \n ' );
42344265
4235- OS.write (Section.getOutputContents ().data (), Section.getOutputSize ());
4236- NextAvailableOffset += Section.getOutputSize ();
4266+ NextAvailableOffset += Section.write (OS);
42374267 }
42384268}
42394269
@@ -4347,6 +4377,10 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
43474377 BinarySection *BinSec = BC->getSectionForSectionRef (SecRef);
43484378 assert (BinSec && " Matching BinarySection should exist." );
43494379
4380+ // Exclude anonymous sections.
4381+ if (BinSec->isAnonymous ())
4382+ continue ;
4383+
43504384 addSection (Section, *BinSec);
43514385 }
43524386
@@ -5699,8 +5733,8 @@ void RewriteInstance::rewriteFile() {
56995733 << Twine::utohexstr (Section.getAllocAddress ()) << " \n of size "
57005734 << Section.getOutputSize () << " \n at offset "
57015735 << Section.getOutputFileOffset () << ' \n ' ;
5702- OS.pwrite ( reinterpret_cast < const char *>( Section.getOutputData ()),
5703- Section.getOutputSize (), Section. getOutputFileOffset () );
5736+ OS.seek ( Section.getOutputFileOffset ());
5737+ Section.write (OS );
57045738 }
57055739
57065740 for (BinarySection &Section : BC->allocatableSections ())
@@ -5791,42 +5825,64 @@ void RewriteInstance::writeEHFrameHeader() {
57915825 LLVM_DEBUG (dbgs () << " BOLT: writing a new " << getEHFrameHdrSectionName ()
57925826 << ' \n ' );
57935827
5794- NextAvailableAddress =
5795- appendPadding (Out->os (), NextAvailableAddress, EHFrameHdrAlign);
5828+ // Try to overwrite the original .eh_frame_hdr if the size permits.
5829+ uint64_t EHFrameHdrOutputAddress = 0 ;
5830+ uint64_t EHFrameHdrFileOffset = 0 ;
5831+ std::vector<char > NewEHFrameHdr;
5832+ BinarySection *OldEHFrameHdrSection = getSection (getEHFrameHdrSectionName ());
5833+ if (OldEHFrameHdrSection) {
5834+ NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader (
5835+ RelocatedEHFrame, NewEHFrame, OldEHFrameHdrSection->getAddress ());
5836+ if (NewEHFrameHdr.size () <= OldEHFrameHdrSection->getSize ()) {
5837+ BC->outs () << " BOLT-INFO: rewriting " << getEHFrameHdrSectionName ()
5838+ << " in-place\n " ;
5839+ EHFrameHdrOutputAddress = OldEHFrameHdrSection->getAddress ();
5840+ EHFrameHdrFileOffset = OldEHFrameHdrSection->getInputFileOffset ();
5841+ } else {
5842+ OldEHFrameHdrSection->setOutputName (getOrgSecPrefix () +
5843+ getEHFrameHdrSectionName ());
5844+ OldEHFrameHdrSection = nullptr ;
5845+ }
5846+ }
57965847
5797- const uint64_t EHFrameHdrOutputAddress = NextAvailableAddress;
5798- const uint64_t EHFrameHdrFileOffset =
5799- getFileOffsetForAddress (NextAvailableAddress);
5848+ // If there was not enough space, allocate more memory for .eh_frame_hdr.
5849+ if (!OldEHFrameHdrSection) {
5850+ NextAvailableAddress =
5851+ appendPadding (Out->os (), NextAvailableAddress, EHFrameHdrAlign);
58005852
5801- std::vector<char > NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader (
5802- RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress);
5853+ EHFrameHdrOutputAddress = NextAvailableAddress;
5854+ EHFrameHdrFileOffset = getFileOffsetForAddress (NextAvailableAddress);
5855+
5856+ NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader (
5857+ RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress);
5858+
5859+ NextAvailableAddress += NewEHFrameHdr.size ();
5860+ if (!BC->BOLTReserved .empty () &&
5861+ (NextAvailableAddress > BC->BOLTReserved .end ())) {
5862+ BC->errs () << " BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName ()
5863+ << " into reserved space\n " ;
5864+ exit (1 );
5865+ }
5866+
5867+ // Create a new entry in the section header table.
5868+ const unsigned Flags = BinarySection::getFlags (/* IsReadOnly=*/ true ,
5869+ /* IsText=*/ false ,
5870+ /* IsAllocatable=*/ true );
5871+ BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection (
5872+ getNewSecPrefix () + getEHFrameHdrSectionName (), ELF::SHT_PROGBITS,
5873+ Flags, nullptr , NewEHFrameHdr.size (), /* Alignment=*/ 1 );
5874+ EHFrameHdrSec.setOutputFileOffset (EHFrameHdrFileOffset);
5875+ EHFrameHdrSec.setOutputAddress (EHFrameHdrOutputAddress);
5876+ EHFrameHdrSec.setOutputName (getEHFrameHdrSectionName ());
5877+ }
58035878
58045879 Out->os ().seek (EHFrameHdrFileOffset);
58055880 Out->os ().write (NewEHFrameHdr.data (), NewEHFrameHdr.size ());
58065881
5807- const unsigned Flags = BinarySection::getFlags (/* IsReadOnly=*/ true ,
5808- /* IsText=*/ false ,
5809- /* IsAllocatable=*/ true );
5810- BinarySection *OldEHFrameHdrSection = getSection (getEHFrameHdrSectionName ());
5882+ // Pad the contents if overwriting in-place.
58115883 if (OldEHFrameHdrSection)
5812- OldEHFrameHdrSection->setOutputName (getOrgSecPrefix () +
5813- getEHFrameHdrSectionName ());
5814-
5815- BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection (
5816- getNewSecPrefix () + getEHFrameHdrSectionName (), ELF::SHT_PROGBITS, Flags,
5817- nullptr , NewEHFrameHdr.size (), /* Alignment=*/ 1 );
5818- EHFrameHdrSec.setOutputFileOffset (EHFrameHdrFileOffset);
5819- EHFrameHdrSec.setOutputAddress (EHFrameHdrOutputAddress);
5820- EHFrameHdrSec.setOutputName (getEHFrameHdrSectionName ());
5821-
5822- NextAvailableAddress += EHFrameHdrSec.getOutputSize ();
5823-
5824- if (!BC->BOLTReserved .empty () &&
5825- (NextAvailableAddress > BC->BOLTReserved .end ())) {
5826- BC->errs () << " BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName ()
5827- << " into reserved space\n " ;
5828- exit (1 );
5829- }
5884+ Out->os ().write_zeros (OldEHFrameHdrSection->getSize () -
5885+ NewEHFrameHdr.size ());
58305886
58315887 // Merge new .eh_frame with the relocated original so that gdb can locate all
58325888 // FDEs.
0 commit comments