@@ -708,9 +708,13 @@ Error RewriteInstance::run() {
708708 adjustCommandLineOptions ();
709709 discoverFileObjects ();
710710
711- if (opts::Instrument && !BC->IsStaticExecutable )
711+ if (opts::Instrument && !BC->IsStaticExecutable ) {
712+ if (!BC->HasInterpHeader )
713+ if (Error E = discoverRtInitAddress ())
714+ return E;
712715 if (Error E = discoverRtFiniAddress ())
713716 return E;
717+ }
714718
715719 preprocessProfileData ();
716720
@@ -752,8 +756,10 @@ Error RewriteInstance::run() {
752756
753757 updateMetadata ();
754758
755- if (opts::Instrument && !BC->IsStaticExecutable )
759+ if (opts::Instrument && !BC->IsStaticExecutable ) {
760+ updateRtInitReloc ();
756761 updateRtFiniReloc ();
762+ }
757763
758764 if (opts::OutputFilename == " /dev/null" ) {
759765 BC->outs () << " BOLT-INFO: skipping writing final binary to disk\n " ;
@@ -1381,6 +1387,46 @@ void RewriteInstance::discoverBOLTReserved() {
13811387 NextAvailableAddress = BC->BOLTReserved .start ();
13821388}
13831389
1390+ Error RewriteInstance::discoverRtInitAddress () {
1391+ // Use init address if it is available.
1392+ if (BC->InitAddress ) {
1393+ BC->StartFunctionAddress = BC->InitAddress ;
1394+ return Error::success ();
1395+ }
1396+
1397+ if (BC->InitArrayAddress || BC->InitArraySize ) {
1398+ if (*BC->InitArraySize < BC->AsmInfo ->getCodePointerSize ()) {
1399+ return createStringError (std::errc::not_supported,
1400+ " Need at least 1 DT_INIT_ARRAY slot" );
1401+ }
1402+
1403+ ErrorOr<BinarySection &> InitArraySection =
1404+ BC->getSectionForAddress (*BC->InitArrayAddress );
1405+ if (auto EC = InitArraySection.getError ())
1406+ return errorCodeToError (EC);
1407+
1408+ if (const Relocation *Reloc = InitArraySection->getDynamicRelocationAt (0 )) {
1409+ BC->StartFunctionAddress = Reloc->Addend ;
1410+ return Error::success ();
1411+ }
1412+
1413+ if (const Relocation *Reloc = InitArraySection->getRelocationAt (0 )) {
1414+ BC->StartFunctionAddress = Reloc->Value ;
1415+ return Error::success ();
1416+ }
1417+
1418+ return createStringError (std::errc::not_supported,
1419+ " No relocation for first DT_INIT_ARRAY slot" );
1420+ }
1421+
1422+ if (BC->StartFunctionAddress && BC->StartFunctionAddress .value () != 0 )
1423+ return Error::success ();
1424+
1425+ return createStringError (
1426+ std::errc::not_supported,
1427+ " Instrumentation needs any of ELF e_entry, DT_INIT or DT_INIT_ARRAY" );
1428+ }
1429+
13841430Error RewriteInstance::discoverRtFiniAddress () {
13851431 // Use DT_FINI if it's available.
13861432 if (BC->FiniAddress ) {
@@ -1452,6 +1498,40 @@ void RewriteInstance::updateRtFiniReloc() {
14521498 /* Addend*/ RT->getRuntimeFiniAddress (), /* Value*/ 0 });
14531499}
14541500
1501+ void RewriteInstance::updateRtInitReloc () {
1502+ // Updating DT_INIT is handled by patchELFDynamic.
1503+ if (BC->InitAddress || !BC->InitArrayAddress )
1504+ return ;
1505+
1506+ const RuntimeLibrary *RT = BC->getRuntimeLibrary ();
1507+ if (!RT || !RT->getRuntimeStartAddress ())
1508+ return ;
1509+
1510+ assert (BC->InitArrayAddress && BC->InitArraySize &&
1511+ " inconsistent .init_array state" );
1512+
1513+ ErrorOr<BinarySection &> InitArraySection =
1514+ BC->getSectionForAddress (*BC->InitArrayAddress );
1515+ assert (InitArraySection && " .init_array removed" );
1516+
1517+ if (std::optional<Relocation> Reloc =
1518+ InitArraySection->takeDynamicRelocationAt (0 )) {
1519+ assert (Reloc->Addend == BC->StartFunctionAddress &&
1520+ " inconsistent .init_array dynamic relocation" );
1521+ Reloc->Addend = RT->getRuntimeStartAddress ();
1522+ InitArraySection->addDynamicRelocation (*Reloc);
1523+ }
1524+
1525+ // Update the static relocation by adding a pending relocation which will get
1526+ // patched when flushPendingRelocations is called in rewriteFile. Note that
1527+ // flushPendingRelocations will calculate the value to patch as
1528+ // "Symbol + Addend". Since we don't have a symbol, just set the addend to the
1529+ // desired value.
1530+ InitArraySection->addPendingRelocation (Relocation{
1531+ /* Offset*/ 0 , /* Symbol*/ nullptr , /* Type*/ Relocation::getAbs64 (),
1532+ /* Addend*/ RT->getRuntimeStartAddress (), /* Value*/ 0 });
1533+ }
1534+
14551535void RewriteInstance::registerFragments () {
14561536 if (!BC->HasSplitFunctions ||
14571537 opts::HeatmapMode == opts::HeatmapModeKind::HM_Exclusive)
@@ -5705,8 +5785,18 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
57055785 switch (Dyn.d_tag ) {
57065786 case ELF::DT_INIT:
57075787 if (!BC->HasInterpHeader ) {
5708- LLVM_DEBUG (dbgs () << " BOLT-DEBUG: Set start function address\n " );
5709- BC->StartFunctionAddress = Dyn.getPtr ();
5788+ LLVM_DEBUG (dbgs () << " BOLT-DEBUG: Set init address\n " );
5789+ BC->InitAddress = Dyn.getPtr ();
5790+ }
5791+ break ;
5792+ case ELF::DT_INIT_ARRAY:
5793+ if (!BC->HasInterpHeader ) {
5794+ BC->InitArrayAddress = Dyn.getPtr ();
5795+ }
5796+ break ;
5797+ case ELF::DT_INIT_ARRAYSZ:
5798+ if (!BC->HasInterpHeader ) {
5799+ BC->InitArraySize = Dyn.getPtr ();
57105800 }
57115801 break ;
57125802 case ELF::DT_FINI:
0 commit comments