[llvm] [BOLT] Support instrumentation hook via DT_FINI_ARRAY (PR #67348)
Vladislav Khmelevsky via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 4 00:49:13 PDT 2023
================
@@ -1276,6 +1282,68 @@ 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)
----------------
yota9 wrote:
Not exactly, currently you at discoverRtFiniAddress you also set FiniFunctionAddress. As I understand it is caused by the internal logic, which uses it to call the original function from new instrumentation fini.
I didn't notice it before to be honest, but the problem with your current change that after you set the FiniFunctionAddress you can't distinguish between the case where DT_FINI was originally in the binary and you don't have to patch DT_FINI_ARRAY and your case where you should. Correct me if I'm wrong.
So you need to check that FiniFunctionAddress == Reloc->Value of the first dynamic slot to continue patching at least.
My suggestion is to use FiniFunctionAddress for DT_FINI only (probably fix the comment about it) and add FiniFunctionRtAddress and check that FiniFunctionAddress != FiniFunctionRtAddress with the comment that DT_FINI is fixed during patching DYNAMIC. After it I would probably add assert to BC->FiniArrayAddress && BC->FiniArraySize just in case. And one more assert after successfully taking takeDynamicRelocationAt with BC->FiniFunctionRtAddress == Reloc->Addend; This way it seems to be less frustrating and also gives ability to rewrite comparing the addresses if would want to use not only DT_FINI and DT_FINI_ARRAY in the future (unlikely, but still).
https://github.com/llvm/llvm-project/pull/67348
More information about the llvm-commits
mailing list