@@ -1063,6 +1063,11 @@ void RewriteInstance::discoverFileObjects() {
1063
1063
continue ;
1064
1064
}
1065
1065
1066
+ if (SymName == getBOLTReservedStart () || SymName == getBOLTReservedEnd ()) {
1067
+ registerName (SymbolSize);
1068
+ continue ;
1069
+ }
1070
+
1066
1071
LLVM_DEBUG (dbgs () << " BOLT-DEBUG: considering symbol " << UniqueName
1067
1072
<< " for function\n " );
1068
1073
@@ -3594,6 +3599,26 @@ void RewriteInstance::updateMetadata() {
3594
3599
void RewriteInstance::mapFileSections (BOLTLinker::SectionMapper MapSection) {
3595
3600
BC->deregisterUnusedSections ();
3596
3601
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
+
3597
3622
// If no new .eh_frame was written, remove relocated original .eh_frame.
3598
3623
BinarySection *RelocatedEHFrameSection =
3599
3624
getSection (" .relocated" + getEHFrameSectionName ());
@@ -3613,6 +3638,18 @@ void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) {
3613
3638
3614
3639
// Map the rest of the sections.
3615
3640
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
+ }
3616
3653
}
3617
3654
3618
3655
std::vector<BinarySection *> RewriteInstance::getCodeSections () {
@@ -3854,7 +3891,7 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
3854
3891
// Add the new text section aggregating all existing code sections.
3855
3892
// This is pseudo-section that serves a purpose of creating a corresponding
3856
3893
// entry in section header table.
3857
- int64_t NewTextSectionSize =
3894
+ const uint64_t NewTextSectionSize =
3858
3895
NextAvailableAddress - NewTextSectionStartAddress;
3859
3896
if (NewTextSectionSize) {
3860
3897
const unsigned Flags = BinarySection::getFlags (/* IsReadOnly=*/ true ,
@@ -3937,7 +3974,7 @@ void RewriteInstance::mapAllocatableSections(
3937
3974
if (PHDRTableAddress) {
3938
3975
// Segment size includes the size of the PHDR area.
3939
3976
NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress;
3940
- } else {
3977
+ } else if (NewTextSegmentAddress) {
3941
3978
// Existing PHDR table would be updated.
3942
3979
NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
3943
3980
}
@@ -3976,7 +4013,7 @@ void RewriteInstance::patchELFPHDRTable() {
3976
4013
assert (!PHDRTableAddress && " unexpected address for program header table" );
3977
4014
PHDRTableOffset = Obj.getHeader ().e_phoff ;
3978
4015
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 " ;
3980
4017
exit (1 );
3981
4018
}
3982
4019
}
@@ -3986,7 +4023,7 @@ void RewriteInstance::patchELFPHDRTable() {
3986
4023
if (!NewWritableSegmentSize) {
3987
4024
if (PHDRTableAddress)
3988
4025
NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress;
3989
- else
4026
+ else if (NewTextSegmentAddress)
3990
4027
NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
3991
4028
} else {
3992
4029
NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;
@@ -4020,8 +4057,10 @@ void RewriteInstance::patchELFPHDRTable() {
4020
4057
};
4021
4058
4022
4059
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
+ }
4025
4064
4026
4065
if (NewWritableSegmentSize) {
4027
4066
ELF64LEPhdrTy NewPhdr;
@@ -4119,9 +4158,8 @@ void RewriteInstance::rewriteNoteSections() {
4119
4158
const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile ();
4120
4159
raw_fd_ostream &OS = Out->os ();
4121
4160
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);
4125
4163
OS.seek (NextAvailableOffset);
4126
4164
4127
4165
// Copy over non-allocatable section contents and update file offsets.
@@ -4860,7 +4898,7 @@ void RewriteInstance::updateELFSymbolTable(
4860
4898
++NumHotDataSymsUpdated;
4861
4899
}
4862
4900
4863
- if (*SymbolName == " _end" )
4901
+ if (*SymbolName == " _end" && NextAvailableAddress > Symbol. st_value )
4864
4902
updateSymbolValue (*SymbolName, NextAvailableAddress);
4865
4903
4866
4904
if (IsDynSym)
@@ -4974,13 +5012,6 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
4974
5012
std::vector<uint32_t > NewSectionIndex;
4975
5013
getOutputSections (File, NewSectionIndex);
4976
5014
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
-
4984
5015
// Update dynamic symbol table.
4985
5016
const ELFShdrTy *DynSymSection = nullptr ;
4986
5017
for (const ELFShdrTy &Section : cantFail (Obj.sections ())) {
@@ -4992,6 +5023,10 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
4992
5023
assert ((DynSymSection || BC->IsStaticExecutable ) &&
4993
5024
" dynamic symbol table expected" );
4994
5025
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
+
4995
5030
updateELFSymbolTable (
4996
5031
File,
4997
5032
/* IsDynSym=*/ true ,
@@ -5545,10 +5580,10 @@ void RewriteInstance::rewriteFile() {
5545
5580
auto Streamer = BC->createStreamer (OS);
5546
5581
// Make sure output stream has enough reserved space, otherwise
5547
5582
// 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" );
5552
5587
5553
5588
// Overwrite functions with fixed output address. This is mostly used by
5554
5589
// non-relocation mode, with one exception: injected functions are covered
@@ -5780,7 +5815,7 @@ void RewriteInstance::writeEHFrameHeader() {
5780
5815
std::vector<char > NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader (
5781
5816
RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses);
5782
5817
5783
- assert ( Out->os ().tell () == EHFrameHdrFileOffset && " offset mismatch " );
5818
+ Out->os ().seek ( EHFrameHdrFileOffset);
5784
5819
Out->os ().write (NewEHFrameHdr.data (), NewEHFrameHdr.size ());
5785
5820
5786
5821
const unsigned Flags = BinarySection::getFlags (/* IsReadOnly=*/ true ,
@@ -5800,6 +5835,15 @@ void RewriteInstance::writeEHFrameHeader() {
5800
5835
5801
5836
NextAvailableAddress += EHFrameHdrSec.getOutputSize ();
5802
5837
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
+
5803
5847
// Merge new .eh_frame with the relocated original so that gdb can locate all
5804
5848
// FDEs.
5805
5849
if (RelocatedEHFrameSection) {
0 commit comments