@@ -80,6 +80,7 @@ namespace opts {
8080extern cl::list<std::string> HotTextMoveSections;
8181extern cl::opt<bool > Hugify;
8282extern cl::opt<bool > Instrument;
83+ extern cl::opt<bool > InstrumentNoUseEntryPoint;
8384extern cl::opt<bool > KeepNops;
8485extern cl::opt<bool > Lite;
8586extern cl::list<std::string> ReorderData;
@@ -737,9 +738,12 @@ Error RewriteInstance::run() {
737738 adjustCommandLineOptions ();
738739 discoverFileObjects ();
739740
740- if (opts::Instrument && !BC->IsStaticExecutable )
741+ if (opts::Instrument && !BC->IsStaticExecutable ) {
742+ if (Error E = discoverRtInitAddress ())
743+ return E;
741744 if (Error E = discoverRtFiniAddress ())
742745 return E;
746+ }
743747
744748 preprocessProfileData ();
745749
@@ -781,8 +785,10 @@ Error RewriteInstance::run() {
781785
782786 updateMetadata ();
783787
784- if (opts::Instrument && !BC->IsStaticExecutable )
788+ if (opts::Instrument && !BC->IsStaticExecutable ) {
789+ updateRtInitReloc ();
785790 updateRtFiniReloc ();
791+ }
786792
787793 if (opts::OutputFilename == " /dev/null" ) {
788794 BC->outs () << " BOLT-INFO: skipping writing final binary to disk\n " ;
@@ -1407,6 +1413,55 @@ void RewriteInstance::discoverBOLTReserved() {
14071413 NextAvailableAddress = BC->BOLTReserved .start ();
14081414}
14091415
1416+ Error RewriteInstance::discoverRtInitAddress () {
1417+ if (BC->HasInterpHeader && !opts::InstrumentNoUseEntryPoint)
1418+ return Error::success ();
1419+
1420+ // Use DT_INIT if it's available.
1421+ if (BC->InitAddress ) {
1422+ BC->StartFunctionAddress = BC->InitAddress ;
1423+ return Error::success ();
1424+ }
1425+
1426+ if (!BC->InitArrayAddress || !BC->InitArraySize ) {
1427+ return createStringError (std::errc::not_supported,
1428+ " Instrumentation of shared library needs either "
1429+ " DT_INIT or DT_INIT_ARRAY" );
1430+ }
1431+
1432+ if (*BC->InitArraySize < BC->AsmInfo ->getCodePointerSize ()) {
1433+ return createStringError (std::errc::not_supported,
1434+ " Need at least 1 DT_FINI_ARRAY slot" );
1435+ }
1436+
1437+ ErrorOr<BinarySection &> InitArraySection =
1438+ BC->getSectionForAddress (*BC->InitArrayAddress );
1439+ if (auto EC = InitArraySection.getError ())
1440+ return errorCodeToError (EC);
1441+
1442+ if (const Relocation *Reloc = InitArraySection->getDynamicRelocationAt (0 )) {
1443+ if (Reloc->isRelative ()) {
1444+ BC->StartFunctionAddress = Reloc->Addend ;
1445+ } else {
1446+ MCSymbol *Sym = Reloc->Symbol ;
1447+ assert (Sym && " Failed to locate symbol for 0 entry of .init_array" );
1448+ const BinaryFunction *BF = BC->getFunctionForSymbol (Sym);
1449+ assert (BF &&
1450+ " Failed to locate binary function for 0 entry of .init_array" );
1451+ BC->StartFunctionAddress = BF->getAddress () + Reloc->Addend ;
1452+ }
1453+ return Error::success ();
1454+ }
1455+
1456+ if (const Relocation *Reloc = InitArraySection->getRelocationAt (0 )) {
1457+ BC->StartFunctionAddress = Reloc->Value ;
1458+ return Error::success ();
1459+ }
1460+
1461+ return createStringError (std::errc::not_supported,
1462+ " No relocation for first DT_INIT_ARRAY slot" );
1463+ }
1464+
14101465Error RewriteInstance::discoverRtFiniAddress () {
14111466 // Use DT_FINI if it's available.
14121467 if (BC->FiniAddress ) {
@@ -1444,6 +1499,58 @@ Error RewriteInstance::discoverRtFiniAddress() {
14441499 " No relocation for first DT_FINI_ARRAY slot" );
14451500}
14461501
1502+ void RewriteInstance::updateRtInitReloc () {
1503+ if (BC->HasInterpHeader && !opts::InstrumentNoUseEntryPoint)
1504+ return ;
1505+
1506+ // Updating DT_INIT is handled by patchELFDynamic.
1507+ if (BC->InitAddress )
1508+ return ;
1509+
1510+ const RuntimeLibrary *RT = BC->getRuntimeLibrary ();
1511+ if (!RT || !RT->getRuntimeStartAddress ())
1512+ return ;
1513+
1514+ if (!BC->InitArrayAddress )
1515+ return ;
1516+
1517+ assert (BC->InitArrayAddress && BC->InitArraySize &&
1518+ " inconsistent .init_array state" );
1519+
1520+ ErrorOr<BinarySection &> InitArraySection =
1521+ BC->getSectionForAddress (*BC->InitArrayAddress );
1522+ assert (InitArraySection && " .init_array removed" );
1523+
1524+ if (std::optional<Relocation> Reloc =
1525+ InitArraySection->takeDynamicRelocationAt (0 )) {
1526+ if (Reloc->isRelative ()) {
1527+ assert (Reloc->Addend == BC->StartFunctionAddress &&
1528+ " inconsistent .init_array dynamic relocation" );
1529+ Reloc->Addend = RT->getRuntimeStartAddress ();
1530+ InitArraySection->addDynamicRelocation (*Reloc);
1531+ } else {
1532+ MCSymbol *Sym = Reloc->Symbol ;
1533+ assert (Sym && " Failed to locate symbol for 0 entry of .init_array" );
1534+ const BinaryFunction *BF = BC->getFunctionForSymbol (Sym);
1535+ assert (BF &&
1536+ " Failed to locate binary function for 0 entry of .init_array" );
1537+ assert (BF->getAddress () + Reloc->Addend == BC->StartFunctionAddress &&
1538+ " inconsistent .init_array dynamic relocation" );
1539+ InitArraySection->addDynamicRelocation (Relocation{
1540+ /* Offset*/ 0 , /* Symbol*/ nullptr , /* Type*/ Relocation::getAbs64 (),
1541+ /* Addend*/ RT->getRuntimeStartAddress (), /* Value*/ 0 });
1542+ }
1543+ }
1544+ // Update the static relocation by adding a pending relocation which will get
1545+ // patched when flushPendingRelocations is called in rewriteFile. Note that
1546+ // flushPendingRelocations will calculate the value to patch as
1547+ // "Symbol + Addend". Since we don't have a symbol, just set the addend to the
1548+ // desired value.
1549+ InitArraySection->addPendingRelocation (Relocation{
1550+ /* Offset*/ 0 , /* Symbol*/ nullptr , /* Type*/ Relocation::getAbs64 (),
1551+ /* Addend*/ RT->getRuntimeStartAddress (), /* Value*/ 0 });
1552+ }
1553+
14471554void RewriteInstance::updateRtFiniReloc () {
14481555 // Updating DT_FINI is handled by patchELFDynamic.
14491556 if (BC->FiniAddress )
@@ -4838,7 +4945,8 @@ void RewriteInstance::patchELFSectionHeaderTable(ELFObjectFile<ELFT> *File) {
48384945 ELFEhdrTy NewEhdr = Obj.getHeader ();
48394946
48404947 if (BC->HasRelocations ) {
4841- if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary ())
4948+ RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary ();
4949+ if (RtLibrary && !opts::InstrumentNoUseEntryPoint)
48424950 NewEhdr.e_entry = RtLibrary->getRuntimeStartAddress ();
48434951 else
48444952 NewEhdr.e_entry = getNewFunctionAddress (NewEhdr.e_entry );
@@ -5684,7 +5792,8 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) {
56845792 if (uint64_t Addr = RtLibrary->getRuntimeFiniAddress ())
56855793 NewDE.d_un .d_ptr = Addr;
56865794 }
5687- if (RtLibrary && Dyn.getTag () == ELF::DT_INIT && !BC->HasInterpHeader ) {
5795+ if (RtLibrary && Dyn.getTag () == ELF::DT_INIT &&
5796+ (!BC->HasInterpHeader || opts::InstrumentNoUseEntryPoint)) {
56885797 if (auto Addr = RtLibrary->getRuntimeStartAddress ()) {
56895798 LLVM_DEBUG (dbgs () << " BOLT-DEBUG: Set DT_INIT to 0x"
56905799 << Twine::utohexstr (Addr) << ' \n ' );
@@ -5760,6 +5869,13 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
57605869 LLVM_DEBUG (dbgs () << " BOLT-DEBUG: Set start function address\n " );
57615870 BC->StartFunctionAddress = Dyn.getPtr ();
57625871 }
5872+ BC->InitAddress = Dyn.getPtr ();
5873+ break ;
5874+ case ELF::DT_INIT_ARRAY:
5875+ BC->InitArrayAddress = Dyn.getPtr ();
5876+ break ;
5877+ case ELF::DT_INIT_ARRAYSZ:
5878+ BC->InitArraySize = Dyn.getPtr ();
57635879 break ;
57645880 case ELF::DT_FINI:
57655881 BC->FiniAddress = Dyn.getPtr ();
0 commit comments