@@ -1063,6 +1063,11 @@ void RewriteInstance::discoverFileObjects() {
10631063 continue ;
10641064 }
10651065
1066+ if (SymName == getBOLTReservedStart () || SymName == getBOLTReservedEnd ()) {
1067+ registerName (SymbolSize);
1068+ continue ;
1069+ }
1070+
10661071 LLVM_DEBUG (dbgs () << " BOLT-DEBUG: considering symbol " << UniqueName
10671072 << " for function\n " );
10681073
@@ -3594,6 +3599,26 @@ void RewriteInstance::updateMetadata() {
35943599void RewriteInstance::mapFileSections (BOLTLinker::SectionMapper MapSection) {
35953600 BC->deregisterUnusedSections ();
35963601
3602+ // Check if the input has a space reserved for BOLT.
3603+ BinaryData *StartBD = BC->getBinaryDataByName (getBOLTReservedStart ());
3604+ BinaryData *EndBD = BC->getBinaryDataByName (getBOLTReservedEnd ());
3605+ if (!StartBD != !EndBD) {
3606+ BC->errs () << " BOLT-ERROR: one of the symbols is missing from the binary: "
3607+ << getBOLTReservedStart () << " , " << getBOLTReservedEnd ()
3608+ << ' \n ' ;
3609+ exit (1 );
3610+ }
3611+
3612+ if (StartBD) {
3613+ PHDRTableOffset = 0 ;
3614+ PHDRTableAddress = 0 ;
3615+ NewTextSegmentAddress = 0 ;
3616+ NewTextSegmentOffset = 0 ;
3617+ NextAvailableAddress = StartBD->getAddress ();
3618+ BC->outs ()
3619+ << " BOLT-INFO: using reserved space for allocating new sections\n " ;
3620+ }
3621+
35973622 // If no new .eh_frame was written, remove relocated original .eh_frame.
35983623 BinarySection *RelocatedEHFrameSection =
35993624 getSection (" .relocated" + getEHFrameSectionName ());
@@ -3613,6 +3638,18 @@ void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) {
36133638
36143639 // Map the rest of the sections.
36153640 mapAllocatableSections (MapSection);
3641+
3642+ if (StartBD) {
3643+ const uint64_t ReservedSpace = EndBD->getAddress () - StartBD->getAddress ();
3644+ const uint64_t AllocatedSize = NextAvailableAddress - StartBD->getAddress ();
3645+ if (ReservedSpace < AllocatedSize) {
3646+ BC->errs () << " BOLT-ERROR: reserved space (" << ReservedSpace << " byte"
3647+ << (ReservedSpace == 1 ? " " : " s" )
3648+ << " ) is smaller than required for new allocations ("
3649+ << AllocatedSize << " bytes)\n " ;
3650+ exit (1 );
3651+ }
3652+ }
36163653}
36173654
36183655std::vector<BinarySection *> RewriteInstance::getCodeSections () {
@@ -3854,7 +3891,7 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
38543891 // Add the new text section aggregating all existing code sections.
38553892 // This is pseudo-section that serves a purpose of creating a corresponding
38563893 // entry in section header table.
3857- int64_t NewTextSectionSize =
3894+ const uint64_t NewTextSectionSize =
38583895 NextAvailableAddress - NewTextSectionStartAddress;
38593896 if (NewTextSectionSize) {
38603897 const unsigned Flags = BinarySection::getFlags (/* IsReadOnly=*/ true ,
@@ -3937,7 +3974,7 @@ void RewriteInstance::mapAllocatableSections(
39373974 if (PHDRTableAddress) {
39383975 // Segment size includes the size of the PHDR area.
39393976 NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress;
3940- } else {
3977+ } else if (NewTextSegmentAddress) {
39413978 // Existing PHDR table would be updated.
39423979 NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
39433980 }
@@ -3976,7 +4013,7 @@ void RewriteInstance::patchELFPHDRTable() {
39764013 assert (!PHDRTableAddress && " unexpected address for program header table" );
39774014 PHDRTableOffset = Obj.getHeader ().e_phoff ;
39784015 if (NewWritableSegmentSize) {
3979- BC->errs () << " Unable to add writable segment with UseGnuStack option \n " ;
4016+ BC->errs () << " BOLT-ERROR: unable to add writable segment\n " ;
39804017 exit (1 );
39814018 }
39824019 }
@@ -3986,7 +4023,7 @@ void RewriteInstance::patchELFPHDRTable() {
39864023 if (!NewWritableSegmentSize) {
39874024 if (PHDRTableAddress)
39884025 NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress;
3989- else
4026+ else if (NewTextSegmentAddress)
39904027 NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
39914028 } else {
39924029 NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;
@@ -4020,8 +4057,10 @@ void RewriteInstance::patchELFPHDRTable() {
40204057 };
40214058
40224059 auto writeNewSegmentPhdrs = [&]() {
4023- ELF64LE::Phdr NewTextPhdr = createNewTextPhdr ();
4024- OS.write (reinterpret_cast <const char *>(&NewTextPhdr), sizeof (NewTextPhdr));
4060+ if (PHDRTableAddress || NewTextSegmentSize) {
4061+ ELF64LE::Phdr NewPhdr = createNewTextPhdr ();
4062+ OS.write (reinterpret_cast <const char *>(&NewPhdr), sizeof (NewPhdr));
4063+ }
40254064
40264065 if (NewWritableSegmentSize) {
40274066 ELF64LEPhdrTy NewPhdr;
@@ -4119,9 +4158,8 @@ void RewriteInstance::rewriteNoteSections() {
41194158 const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile ();
41204159 raw_fd_ostream &OS = Out->os ();
41214160
4122- uint64_t NextAvailableOffset = getFileOffsetForAddress (NextAvailableAddress);
4123- assert (NextAvailableOffset >= FirstNonAllocatableOffset &&
4124- " next available offset calculation failure" );
4161+ uint64_t NextAvailableOffset = std::max (
4162+ getFileOffsetForAddress (NextAvailableAddress), FirstNonAllocatableOffset);
41254163 OS.seek (NextAvailableOffset);
41264164
41274165 // Copy over non-allocatable section contents and update file offsets.
@@ -4860,7 +4898,7 @@ void RewriteInstance::updateELFSymbolTable(
48604898 ++NumHotDataSymsUpdated;
48614899 }
48624900
4863- if (*SymbolName == " _end" )
4901+ if (*SymbolName == " _end" && NextAvailableAddress > Symbol. st_value )
48644902 updateSymbolValue (*SymbolName, NextAvailableAddress);
48654903
48664904 if (IsDynSym)
@@ -4974,13 +5012,6 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
49745012 std::vector<uint32_t > NewSectionIndex;
49755013 getOutputSections (File, NewSectionIndex);
49765014
4977- // Set pointer at the end of the output file, so we can pwrite old symbol
4978- // tables if we need to.
4979- uint64_t NextAvailableOffset = getFileOffsetForAddress (NextAvailableAddress);
4980- assert (NextAvailableOffset >= FirstNonAllocatableOffset &&
4981- " next available offset calculation failure" );
4982- Out->os ().seek (NextAvailableOffset);
4983-
49845015 // Update dynamic symbol table.
49855016 const ELFShdrTy *DynSymSection = nullptr ;
49865017 for (const ELFShdrTy &Section : cantFail (Obj.sections ())) {
@@ -4992,6 +5023,10 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
49925023 assert ((DynSymSection || BC->IsStaticExecutable ) &&
49935024 " dynamic symbol table expected" );
49945025 if (DynSymSection) {
5026+ // Set pointer to the end of the section, so we can use pwrite to update
5027+ // the dynamic symbol table.
5028+ Out->os ().seek (DynSymSection->sh_offset + DynSymSection->sh_size );
5029+
49955030 updateELFSymbolTable (
49965031 File,
49975032 /* IsDynSym=*/ true ,
@@ -5545,10 +5580,10 @@ void RewriteInstance::rewriteFile() {
55455580 auto Streamer = BC->createStreamer (OS);
55465581 // Make sure output stream has enough reserved space, otherwise
55475582 // pwrite() will fail.
5548- uint64_t Offset = OS. seek (getFileOffsetForAddress (NextAvailableAddress));
5549- ( void )Offset ;
5550- assert ( Offset == getFileOffsetForAddress (NextAvailableAddress) &&
5551- " error resizing output file" );
5583+ uint64_t Offset = std::max (getFileOffsetForAddress (NextAvailableAddress),
5584+ FirstNonAllocatableOffset) ;
5585+ Offset = OS. seek (Offset);
5586+ assert ((Offset != ( uint64_t )- 1 ) && " Error resizing output file" );
55525587
55535588 // Overwrite functions with fixed output address. This is mostly used by
55545589 // non-relocation mode, with one exception: injected functions are covered
@@ -5780,7 +5815,7 @@ void RewriteInstance::writeEHFrameHeader() {
57805815 std::vector<char > NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader (
57815816 RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses);
57825817
5783- assert ( Out->os ().tell () == EHFrameHdrFileOffset && " offset mismatch " );
5818+ Out->os ().seek ( EHFrameHdrFileOffset);
57845819 Out->os ().write (NewEHFrameHdr.data (), NewEHFrameHdr.size ());
57855820
57865821 const unsigned Flags = BinarySection::getFlags (/* IsReadOnly=*/ true ,
@@ -5800,6 +5835,15 @@ void RewriteInstance::writeEHFrameHeader() {
58005835
58015836 NextAvailableAddress += EHFrameHdrSec.getOutputSize ();
58025837
5838+ if (const BinaryData *ReservedEnd =
5839+ BC->getBinaryDataByName (getBOLTReservedEnd ())) {
5840+ if (NextAvailableAddress > ReservedEnd->getAddress ()) {
5841+ BC->errs () << " BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName ()
5842+ << " into reserved space\n " ;
5843+ exit (1 );
5844+ }
5845+ }
5846+
58035847 // Merge new .eh_frame with the relocated original so that gdb can locate all
58045848 // FDEs.
58055849 if (RelocatedEHFrameSection) {
0 commit comments