003 File Manager
Current Path:
/usr/src/contrib/llvm-project/lld/lib/ReaderWriter/MachO
usr
/
src
/
contrib
/
llvm-project
/
lld
/
lib
/
ReaderWriter
/
MachO
/
📁
..
📄
ArchHandler.cpp
(4.36 KB)
📄
ArchHandler.h
(12.86 KB)
📄
ArchHandler_arm.cpp
(54.53 KB)
📄
ArchHandler_arm64.cpp
(33.86 KB)
📄
ArchHandler_x86.cpp
(24.04 KB)
📄
ArchHandler_x86_64.cpp
(33.45 KB)
📄
Atoms.h
(5.45 KB)
📄
CompactUnwindPass.cpp
(21.9 KB)
📄
DebugInfo.h
(2.52 KB)
📄
ExecutableAtoms.h
(4.69 KB)
📄
File.h
(17.28 KB)
📄
FlatNamespaceFile.h
(1.87 KB)
📄
GOTPass.cpp
(6.58 KB)
📄
LayoutPass.cpp
(18.19 KB)
📄
LayoutPass.h
(4.19 KB)
📄
MachOLinkingContext.cpp
(33.61 KB)
📄
MachONormalizedFile.h
(11.47 KB)
📄
MachONormalizedFileBinaryReader.cpp
(22.82 KB)
📄
MachONormalizedFileBinaryUtils.h
(6.93 KB)
📄
MachONormalizedFileBinaryWriter.cpp
(56.33 KB)
📄
MachONormalizedFileFromAtoms.cpp
(61.05 KB)
📄
MachONormalizedFileToAtoms.cpp
(65.46 KB)
📄
MachONormalizedFileYAML.cpp
(31.45 KB)
📄
MachOPasses.h
(1.11 KB)
📄
ObjCPass.cpp
(3.54 KB)
📄
SectCreateFile.h
(3.01 KB)
📄
ShimPass.cpp
(4.59 KB)
📄
StubsPass.cpp
(12.03 KB)
📄
TLVPass.cpp
(4.02 KB)
📄
WriterMachO.cpp
(2.33 KB)
Editing: ShimPass.cpp
//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // // This linker pass updates branch-sites whose target is a different mode // (thumb vs arm). // // Arm code has two instruction encodings thumb and arm. When branching from // one code encoding to another, you need to use an instruction that switches // the instruction mode. Usually the transition only happens at call sites, and // the linker can transform a BL instruction in BLX (or vice versa). But if the // compiler did a tail call optimization and a function ends with a branch (not // branch and link), there is no pc-rel BX instruction. // // The ShimPass looks for pc-rel B instructions that will need to switch mode. // For those cases it synthesizes a shim which does the transition, then // modifies the original atom with the B instruction to target to the shim atom. // //===----------------------------------------------------------------------===// #include "ArchHandler.h" #include "File.h" #include "MachOPasses.h" #include "lld/Common/LLVM.h" #include "lld/Core/DefinedAtom.h" #include "lld/Core/File.h" #include "lld/Core/Reference.h" #include "lld/Core/Simple.h" #include "lld/ReaderWriter/MachOLinkingContext.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" namespace lld { namespace mach_o { class ShimPass : public Pass { public: ShimPass(const MachOLinkingContext &context) : _ctx(context), _archHandler(_ctx.archHandler()), _stubInfo(_archHandler.stubInfo()), _file(*_ctx.make_file<MachOFile>("<mach-o shim pass>")) { _file.setOrdinal(_ctx.getNextOrdinalAndIncrement()); } llvm::Error perform(SimpleFile &mergedFile) override { // Scan all references in all atoms. for (const DefinedAtom *atom : mergedFile.defined()) { for (const Reference *ref : *atom) { // Look at non-call branches. if (!_archHandler.isNonCallBranch(*ref)) continue; const Atom *target = ref->target(); assert(target != nullptr); if (const lld::DefinedAtom *daTarget = dyn_cast<DefinedAtom>(target)) { bool atomIsThumb = _archHandler.isThumbFunction(*atom); bool targetIsThumb = _archHandler.isThumbFunction(*daTarget); if (atomIsThumb != targetIsThumb) updateBranchToUseShim(atomIsThumb, *daTarget, ref); } } } // Exit early if no shims needed. if (_targetToShim.empty()) return llvm::Error::success(); // Sort shim atoms so the layout order is stable. std::vector<const DefinedAtom *> shims; shims.reserve(_targetToShim.size()); for (auto element : _targetToShim) { shims.push_back(element.second); } std::sort(shims.begin(), shims.end(), [](const DefinedAtom *l, const DefinedAtom *r) { return (l->name() < r->name()); }); // Add all shims to master file. for (const DefinedAtom *shim : shims) mergedFile.addAtom(*shim); return llvm::Error::success(); } private: void updateBranchToUseShim(bool thumbToArm, const DefinedAtom& target, const Reference *ref) { // Make file-format specific stub and other support atoms. const DefinedAtom *shim = this->getShim(thumbToArm, target); assert(shim != nullptr); // Switch branch site to target shim atom. const_cast<Reference *>(ref)->setTarget(shim); } const DefinedAtom* getShim(bool thumbToArm, const DefinedAtom& target) { auto pos = _targetToShim.find(&target); if ( pos != _targetToShim.end() ) { // Reuse an existing shim. assert(pos->second != nullptr); return pos->second; } else { // There is no existing shim, so create a new one. const DefinedAtom *shim = _archHandler.createShim(_file, thumbToArm, target); _targetToShim[&target] = shim; return shim; } } const MachOLinkingContext &_ctx; mach_o::ArchHandler &_archHandler; const ArchHandler::StubInfo &_stubInfo; MachOFile &_file; llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToShim; }; void addShimPass(PassManager &pm, const MachOLinkingContext &ctx) { pm.add(std::make_unique<ShimPass>(ctx)); } } // end namespace mach_o } // end namespace lld
Upload File
Create Folder