================ @@ -0,0 +1,94 @@ +//===- 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. +// +// getBranchInfoAtTarget: 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}. +// +// redirectControlTransferRelocations: 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 GetControlTransferAddend, typename GetBranchInfoAtTarget, + typename RedirectControlTransferRelocations> +inline void applyBranchToBranchOptImpl( + Ctx &ctx, GetControlTransferAddend getControlTransferAddend, + GetBranchInfoAtTarget getBranchInfoAtTarget, + RedirectControlTransferRelocations redirectControlTransferRelocations) { + // 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 = + [&getBranchInfoAtTarget]( + 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 or writable + // memory (ditto) or non-regular sections (no section data). + if (!target || target->isPreemptible || target->isGnuIFunc() || + !target->section || + !(target->section->flags & llvm::ELF::SHF_EXECINSTR) || + (target->section->flags & llvm::ELF::SHF_WRITE) || + target->section->kind() != SectionBase::Regular) + return {nullptr, 0}; + return getBranchInfoAtTarget(*cast<InputSection>(target->section), + target->value + addend); + }; + for (InputSectionBase *s : f->getSections()) { + if (!s) + continue; + for (Relocation &r : s->relocations) { + if (std::optional<uint64_t> addend = ---------------- MaskRay wrote:
can use early return for this if the next if to reduce indentation 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