[llvm] [BOLT] Support instrumentation hook via DT_FINI_ARRAY (PR #67348)

Job Noorman via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 3 05:12:05 PDT 2023


================
@@ -1276,6 +1282,69 @@ void RewriteInstance::discoverFileObjects() {
   registerFragments();
 }
 
+Error RewriteInstance::discoverRtFiniAddress() {
+  // If FiniFunctionAddress is already set, we got if from DT_FINI. We use
+  // DT_FINI instead of DT_FINI_ARRAY if it's available.
+  if (BC->FiniFunctionAddress)
+    return Error::success();
+
+  if (!BC->FiniArrayAddress || !BC->FiniArraySize) {
+    return createStringError(
+        std::errc::not_supported,
+        "Instrumentation needs either DT_FINI or DT_FINI_ARRAY");
+  }
+
+  if (*BC->FiniArraySize < BC->AsmInfo->getCodePointerSize()) {
+    return createStringError(std::errc::not_supported,
+                             "Need at least 1 DT_FINI_ARRAY slot");
+  }
+
+  ErrorOr<BinarySection &> FiniArraySection =
+      BC->getSectionForAddress(*BC->FiniArrayAddress);
+  if (auto EC = FiniArraySection.getError())
+    return errorCodeToError(EC);
+
+  BC->FiniArraySection = &*FiniArraySection;
+
+  if (const Relocation *Reloc = FiniArraySection->getDynamicRelocationAt(0)) {
+    BC->FiniFunctionAddress = Reloc->Addend;
+    return Error::success();
+  }
+
+  if (const Relocation *Reloc = FiniArraySection->getRelocationAt(0)) {
+    BC->FiniFunctionAddress = Reloc->Value;
+    return Error::success();
+  }
+
+  return createStringError(std::errc::not_supported,
+                           "No relocation for first DT_FINI_ARRAY slot");
+}
+
+void RewriteInstance::updateRtFiniReloc() {
+  if (!BC->FiniArraySection)
+    return;
+
+  const RuntimeLibrary *RT = BC->getRuntimeLibrary();
+  if (!RT || !RT->getRuntimeFiniAddress())
+    return;
+
+  if (std::optional<Relocation> Reloc =
+          BC->FiniArraySection->takeDynamicRelocationAt(0)) {
+    Reloc->Addend = RT->getRuntimeFiniAddress();
+    BC->FiniArraySection->addDynamicRelocation(*Reloc);
+    return;
+  }
+
+  // There is no dynamic relocation so we have to patch the static one. Add a
----------------
mtvec wrote:

> Is there any reason to skip this in case we have a dynamic relocation?

To be honest, I just assumed there wouldn't be static relocations in that case. I just noticed there actually are so in theory we could patch them. Is there any use for this, though, as the patched values would be ignored at runtime?

> I would patch it and check that the address updated using objdump.

So you propose to patch them for testing purposes only? In that case, wouldn't we be testing something irrelevant since those values are ignored at runtime?

> Also for example if the binary uses RELR we need to patch data address too. I would just patch it everytime.

I might be wrong here (not very familiar with RELR) but isn't this case already handled by `readDynamicRelrRelocations` (which adds dynamic relocations so `discoverFiniAddress` can find them) and `patchELFAllocatableRelrSection` (which writes the new offsets)?

https://github.com/llvm/llvm-project/pull/67348


More information about the llvm-commits mailing list