================ @@ -0,0 +1,92 @@ +//===- TargetImpl.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_ELF_ARCH_TARGETIMPL_H +#define LLD_ELF_ARCH_TARGETIMPL_H + +#include "InputFiles.h" +#include "InputSection.h" +#include "Relocations.h" +#include "Symbols.h" +#include "llvm/BinaryFormat/ELF.h" + +namespace lld { +namespace elf { + +// getControlTransferAddend: If this relocation is used for control transfer +// instructions (e.g. branch, branch-link or call) or code references (e.g. +// virtual function pointers) and indicates an address-insignificant reference, +// return the effective addend for the relocation, otherwise return +// std::nullopt. The effective addend for a relocation is the addend that is +// used to determine its branch destination. +// +// getBranchInfo: If a control transfer relocation referring to is+offset +// directly transfers control to a relocated branch instruction in the specified +// section, return the relocation for the branch target as well as its effective +// addend (see above). Otherwise return {nullptr, 0}. +// +// mergeControlTransferRelocations: Given r1, a relocation for which +// getControlTransferAddend() returned a value, and r2, a relocation returned by +// getBranchInfo(), modify r1 so that it branches directly to the target of r2. +template <typename GetBranchInfo, typename GetControlTransferAddend, + typename MergeControlTransferRelocations> +inline void applyBranchToBranchOptImpl( + Ctx &ctx, GetBranchInfo getBranchInfo, + GetControlTransferAddend getControlTransferAddend, + MergeControlTransferRelocations mergeControlTransferRelocations) { + // Needs to run serially because it writes to the relocations array as well as + // reading relocations of other sections. + for (ELFFileBase *f : ctx.objectFiles) { + auto getRelocBranchInfo = + [&getBranchInfo](Relocation &r, + uint64_t addend) -> std::pair<Relocation *, uint64_t> { + auto *target = dyn_cast_or_null<Defined>(r.sym); + // We don't allow preemptible symbols or ifuncs (may go somewhere else), + // absolute symbols (runtime behavior unknown), non-executable memory + // (ditto) or non-regular sections (no section data). + if (!target || target->isPreemptible || target->isGnuIFunc() || ---------------- smithp35 wrote:
Yes, just checked and it does copy the relocation addend. I agree that this wouldn't need a test case. As an aside when checking where the addends were read in I ran into this bit of copyRelocations https://github.com/llvm/llvm-project/blob/main/lld/ELF/InputSection.cpp#L433 ``` if (ctx.arg.relax && !ctx.arg.relocatable && (ctx.arg.emachine == EM_RISCV || ctx.arg.emachine == EM_LOONGARCH)) { // On LoongArch and RISC-V, relaxation might change relocations: copy // from internal ones that are updated by relaxation. InputSectionBase *sec = getRelocatedSection(); copyRelocations<ELFT, RelTy>( ctx, buf, llvm::make_range(sec->relocations.begin(), sec->relocations.end())); ``` I think I mentioned in a previous comment that bolt uses emit-relocations so it may be worth following suite here when the transformation is applied. I suspect that if bolt trusts the original relocation then in worst case the transformation is undone though. https://github.com/llvm/llvm-project/pull/138366 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits