[lld] r219655 - [mach-o] Add Pass to create are shim Atoms for ARM interworking.

Shankar Easwaran shankare at codeaurora.org
Sat Oct 18 20:13:05 PDT 2014


Hi Nick,

This patch doesnot seem to reuse shim's right ?

Are you planning to add this soon as well ?

Shankar Easwaran

On 10/13/2014 8:51 PM, Nick Kledzik wrote:
> Author: kledzik
> Date: Mon Oct 13 20:51:42 2014
> New Revision: 219655
>
> URL: http://llvm.org/viewvc/llvm-project?rev=219655&view=rev
> Log:
> [mach-o] Add Pass to create are shim Atoms for ARM interworking.
>
> 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.
>
> Added:
>      lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp
>      lld/trunk/test/mach-o/arm-shims.yaml
> Modified:
>      lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
>      lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
>      lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
>      lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
>      lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
>      lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
>      lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
>      lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
>      lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h
>      lld/trunk/test/mach-o/arm-interworking.yaml
>      lld/trunk/test/mach-o/parse-arm-relocs.yaml
>
> Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
> +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Mon Oct 13 20:51:42 2014
> @@ -230,6 +230,9 @@ public:
>     /// Pass to transform __compact_unwind into __unwind_info should be run.
>     bool needsCompactUnwindPass() const;
>   
> +  /// Pass to add shims switching between thumb and arm mode.
> +  bool needsShimPass() const;
> +
>     /// Magic symbol name stubs will need to help lazy bind.
>     StringRef binderSymbolName() const;
>   
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Mon Oct 13 20:51:42 2014
> @@ -9,6 +9,7 @@
>   
>   #include "MachONormalizedFile.h"
>   #include "Atoms.h"
> +#include "File.h"
>   
>   #include "lld/Core/LLVM.h"
>   #include "lld/Core/Reference.h"
> @@ -50,6 +51,9 @@ public:
>       return false;
>     }
>   
> +  /// Used by ShimPass to insert shims in branches that switch mode.
> +  virtual bool isNonCallBranch(const Reference &) = 0;
> +
>     /// Used by GOTPass to update GOT References
>     virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
>   
> @@ -182,6 +186,12 @@ public:
>     /// Only relevant for 32-bit arm archs.
>     virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
>   
> +  /// Only relevant for 32-bit arm archs.
> +  virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
> +                                        const DefinedAtom &) {
> +    llvm_unreachable("shims only support on arm");
> +  }
> +
>     struct ReferenceInfo {
>       Reference::KindArch arch;
>       uint16_t            kind;
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Mon Oct 13 20:51:42 2014
> @@ -36,6 +36,7 @@ public:
>     bool isCallSite(const Reference &) override;
>     bool isPointer(const Reference &) override;
>     bool isPairedReloc(const normalized::Relocation &) override;
> +  bool isNonCallBranch(const Reference &) override;
>   
>     bool needsCompactUnwind() override {
>       return false;
> @@ -106,8 +107,13 @@ public:
>     }
>   
>     bool isThumbFunction(const DefinedAtom &atom) override;
> +  const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
> +                                const DefinedAtom &) override;
>   
>   private:
> +  friend class Thumb2ToArmShimAtom;
> +  friend class ArmToThumbShimAtom;
> +
>     static const Registry::KindStrings _sKindStrings[];
>     static const StubInfo              _sStubInfoArmPIC;
>   
> @@ -119,12 +125,14 @@ private:
>       modeData,              /// Content starting at this offset is data.
>   
>       // Kinds found in mach-o .o files:
> -    thumb_b22,             /// ex: bl _foo
> +    thumb_bl22,            /// ex: bl _foo
> +    thumb_b22,             /// ex: b _foo
>       thumb_movw,            /// ex: movw	r1, :lower16:_foo
>       thumb_movt,            /// ex: movt	r1, :lower16:_foo
>       thumb_movw_funcRel,    /// ex: movw	r1, :lower16:(_foo-(L1+4))
>       thumb_movt_funcRel,    /// ex: movt r1, :upper16:(_foo-(L1+4))
> -    arm_b24,               /// ex: bl _foo
> +    arm_bl24,              /// ex: bl _foo
> +    arm_b24,               /// ex: b _foo
>       arm_movw,              /// ex: movw	r1, :lower16:_foo
>       arm_movt,              /// ex: movt	r1, :lower16:_foo
>       arm_movw_funcRel,      /// ex: movw	r1, :lower16:(_foo-(L1+4))
> @@ -154,6 +162,7 @@ private:
>     static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word);
>     static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word);
>     
> +  StringRef stubName(const DefinedAtom &);
>     bool useExternalRelocationTo(const Atom &target);
>   
>     void applyFixupFinal(const Reference &ref, uint8_t *location,
> @@ -183,11 +192,13 @@ const Registry::KindStrings ArchHandler_
>     LLD_KIND_STRING_ENTRY(modeThumbCode),
>     LLD_KIND_STRING_ENTRY(modeArmCode),
>     LLD_KIND_STRING_ENTRY(modeData),
> +  LLD_KIND_STRING_ENTRY(thumb_bl22),
>     LLD_KIND_STRING_ENTRY(thumb_b22),
>     LLD_KIND_STRING_ENTRY(thumb_movw),
>     LLD_KIND_STRING_ENTRY(thumb_movt),
>     LLD_KIND_STRING_ENTRY(thumb_movw_funcRel),
>     LLD_KIND_STRING_ENTRY(thumb_movt_funcRel),
> +  LLD_KIND_STRING_ENTRY(arm_bl24),
>     LLD_KIND_STRING_ENTRY(arm_b24),
>     LLD_KIND_STRING_ENTRY(arm_movw),
>     LLD_KIND_STRING_ENTRY(arm_movt),
> @@ -256,13 +267,31 @@ const ArchHandler::StubInfo &ArchHandler
>   }
>   
>   bool ArchHandler_arm::isCallSite(const Reference &ref) {
> -  return (ref.kindValue() == thumb_b22) || (ref.kindValue() == arm_b24);
> +  switch (ref.kindValue()) {
> +  case thumb_b22:
> +  case thumb_bl22:
> +  case arm_b24:
> +  case arm_bl24:
> +    return true;
> +  default:
> +    return false;
> +  }
>   }
>   
>   bool ArchHandler_arm::isPointer(const Reference &ref) {
>     return (ref.kindValue() == pointer32);
>   }
>   
> +bool ArchHandler_arm::isNonCallBranch(const Reference &ref) {
> +  switch (ref.kindValue()) {
> +  case thumb_b22:
> +  case arm_b24:
> +    return true;
> +  default:
> +    return false;
> +  }
> +}
> +
>   bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) {
>     switch (reloc.type) {
>     case ARM_RELOC_SECTDIFF:
> @@ -275,6 +304,23 @@ bool ArchHandler_arm::isPairedReloc(cons
>     }
>   }
>   
> +/// Trace references from stub atom to lazy pointer to target and get its name.
> +StringRef ArchHandler_arm::stubName(const DefinedAtom &stubAtom) {
> +  assert(stubAtom.contentType() == DefinedAtom::typeStub);
> +  for (const Reference *ref : stubAtom) {
> +    if (const DefinedAtom* lp = dyn_cast<DefinedAtom>(ref->target())) {
> +      if (lp->contentType() != DefinedAtom::typeLazyPointer)
> +        continue;
> +      for (const Reference *ref2 : *lp) {
> +        if (ref2->kindValue() != lazyPointer)
> +          continue;
> +        return ref2->target()->name();
> +      }
> +    }
> +  }
> +  return "stub";
> +}
> +
>   /// Extract displacement from an ARM b/bl/blx instruction.
>   int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
>     // Sign-extend imm24
> @@ -352,7 +398,7 @@ uint32_t ArchHandler_arm::setDisplacemen
>   	bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
>   	bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
>   	bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
> -  uint32_t newInstruction = (instruction & 0xF800D000);
> +  uint32_t newInstruction = (instruction & 0xD000F800);
>     if (is_bl || is_blx) {
>       if (targetIsThumb) {
>         newInstruction = 0xD000F000; // Use bl
> @@ -363,7 +409,7 @@ uint32_t ArchHandler_arm::setDisplacemen
>           displacement += 2;
>       }
>     } else if (is_b) {
> -    assert(!targetIsThumb && "no pc-rel thumb branch instruction that "
> +    assert(targetIsThumb && "no pc-rel thumb branch instruction that "
>                                "switches to arm mode");
>     }
>     else {
> @@ -461,7 +507,10 @@ std::error_code ArchHandler_arm::getRefe
>     switch (relocPattern(reloc)) {
>     case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
>       // ex: bl _foo (and _foo is undefined)
> -    *kind = thumb_b22;
> +    if ((instruction & 0xD000F800) == 0x9000F000)
> +      *kind = thumb_b22;
> +    else
> +      *kind = thumb_bl22;
>       if (E ec = atomFromSymbolIndex(reloc.symbol, target))
>         return ec;
>       // Instruction contains branch to addend.
> @@ -470,13 +519,19 @@ std::error_code ArchHandler_arm::getRefe
>       return std::error_code();
>     case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
>       // ex: bl _foo (and _foo is defined)
> -    *kind = thumb_b22;
> +    if ((instruction & 0xD000F800) == 0x9000F000)
> +      *kind = thumb_b22;
> +    else
> +      *kind = thumb_bl22;
>       displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
>       targetAddress = fixupAddress + 4 + displacement;
>       return atomFromAddress(reloc.symbol, targetAddress, target, addend);
>     case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
>       // ex: bl _foo+4 (and _foo is defined)
> -    *kind = thumb_b22;
> +    if ((instruction & 0xD000F800) == 0x9000F000)
> +      *kind = thumb_b22;
> +    else
> +      *kind = thumb_bl22;
>       displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
>       targetAddress = fixupAddress + 4 + displacement;
>       if (E ec = atomFromAddress(0, reloc.value, target, addend))
> @@ -487,7 +542,11 @@ std::error_code ArchHandler_arm::getRefe
>       return std::error_code();
>     case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
>       // ex: bl _foo (and _foo is undefined)
> -    *kind = arm_b24;
> +    if (((instruction & 0x0F000000) == 0x0A000000)
> +        && ((instruction & 0xF0000000) != 0xF0000000))
> +      *kind = arm_b24;
> +    else
> +      *kind = arm_bl24;
>       if (E ec = atomFromSymbolIndex(reloc.symbol, target))
>         return ec;
>       // Instruction contains branch to addend.
> @@ -496,13 +555,21 @@ std::error_code ArchHandler_arm::getRefe
>       return std::error_code();
>     case ARM_RELOC_BR24 | rPcRel | rLength4:
>       // ex: bl _foo (and _foo is defined)
> -    *kind = arm_b24;
> +    if (((instruction & 0x0F000000) == 0x0A000000)
> +        && ((instruction & 0xF0000000) != 0xF0000000))
> +      *kind = arm_b24;
> +    else
> +      *kind = arm_bl24;
>       displacement = getDisplacementFromArmBranch(instruction);
>       targetAddress = fixupAddress + 8 + displacement;
>       return atomFromAddress(reloc.symbol, targetAddress, target, addend);
>     case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
>       // ex: bl _foo+4 (and _foo is defined)
> -    *kind = arm_b24;
> +    if (((instruction & 0x0F000000) == 0x0A000000)
> +        && ((instruction & 0xF0000000) != 0xF0000000))
> +      *kind = arm_b24;
> +    else
> +      *kind = arm_bl24;
>       displacement = getDisplacementFromArmBranch(instruction);
>       targetAddress = fixupAddress + 8 + displacement;
>       if (E ec = atomFromAddress(0, reloc.value, target, addend))
> @@ -836,6 +903,7 @@ void ArchHandler_arm::applyFixupFinal(co
>     case modeData:
>       break;
>     case thumb_b22:
> +  case thumb_bl22:
>       assert(thumbMode);
>       displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
>       value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement,
> @@ -867,7 +935,8 @@ void ArchHandler_arm::applyFixupFinal(co
>       write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
>       break;
>     case arm_b24:
> -    assert(!thumbMode);
> +  case arm_bl24:
> +   assert(!thumbMode);
>       displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
>       value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
>       write32(*loc32, _swap, value32);
> @@ -903,7 +972,10 @@ void ArchHandler_arm::applyFixupFinal(co
>         write32(*loc32, _swap, targetAddress + ref.addend());
>       break;
>     case delta32:
> -    write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
> +    if (targetIsThumb)
> +      write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend() + 1);
> +    else
> +      write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
>       break;
>     case lazyPointer:
>     case lazyImmediateLocation:
> @@ -990,6 +1062,7 @@ void ArchHandler_arm::applyFixupRelocata
>     case modeData:
>       break;
>     case thumb_b22:
> +  case thumb_bl22:
>       assert(thumbMode);
>       if (useExternalReloc)
>         displacement = (ref.addend() - (fixupAddress + 4));
> @@ -1026,6 +1099,7 @@ void ArchHandler_arm::applyFixupRelocata
>       write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
>       break;
>     case arm_b24:
> +  case arm_bl24:
>       assert(!thumbMode);
>       if (useExternalReloc)
>         displacement = (ref.addend() - (fixupAddress + 8));
> @@ -1100,6 +1174,7 @@ void ArchHandler_arm::appendSectionReloc
>       // Do nothing.
>       break;
>     case thumb_b22:
> +  case thumb_bl22:
>       if (useExternalReloc) {
>         appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
>                     ARM_THUMB_RELOC_BR22 | rExtern    | rPcRel | rLength4);
> @@ -1179,6 +1254,7 @@ void ArchHandler_arm::appendSectionReloc
>                   ARM_RELOC_PAIR          | rScattered | rLenThmbHi);
>       break;
>     case arm_b24:
> +  case arm_bl24:
>       if (useExternalReloc) {
>         appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
>                     ARM_RELOC_BR24 | rExtern    | rPcRel | rLength4);
> @@ -1307,6 +1383,112 @@ bool ArchHandler_arm::isThumbFunction(co
>     return false;
>   }
>   
> +
> +class Thumb2ToArmShimAtom : public SimpleDefinedAtom {
> +public:
> +  Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName,
> +                      const DefinedAtom &target)
> +      : SimpleDefinedAtom(file) {
> +    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
> +                 ArchHandler_arm::modeThumbCode, 0, this, 0);
> +    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
> +                 ArchHandler_arm::delta32, 8, &target, 0);
> +    std::string name = std::string(targetName) + "$shim";
> +    StringRef tmp(name);
> +    _name = tmp.copy(file.allocator());
> +  }
> +
> +  StringRef name() const override {
> +    return _name;
> +  }
> +
> +  ContentType contentType() const override {
> +    return DefinedAtom::typeCode;
> +  }
> +
> +  Alignment alignment() const override {
> +    return Alignment(2);
> +  }
> +
> +  uint64_t size() const override {
> +    return 12;
> +  }
> +
> +  ContentPermissions permissions() const override {
> +    return DefinedAtom::permR_X;
> +  }
> +
> +  ArrayRef<uint8_t> rawContent() const override {
> +    static const uint8_t bytes[] =
> +    { 0xDF, 0xF8, 0x04, 0xC0,       //  ldr ip, pc + 4
> +      0xFF, 0x44,                   //  add ip, pc, ip
> +      0x60, 0x47,                   //  ldr pc, [ip]
> +      0x00, 0x00, 0x00, 0x00 };     //  .long target - this
> +    assert(sizeof(bytes) == size());
> +    return llvm::makeArrayRef(bytes, sizeof(bytes));
> +  }
> +private:
> +  StringRef _name;
> +};
> +
> +
> +class ArmToThumbShimAtom : public SimpleDefinedAtom {
> +public:
> +  ArmToThumbShimAtom(MachOFile &file, StringRef targetName,
> +                     const DefinedAtom &target)
> +      : SimpleDefinedAtom(file) {
> +    addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
> +                 ArchHandler_arm::delta32, 12, &target, 0);
> +    std::string name = std::string(targetName) + "$shim";
> +    StringRef tmp(name);
> +    _name = tmp.copy(file.allocator());
> +  }
> +
> +  StringRef name() const override {
> +    return _name;
> +  }
> +
> +  ContentType contentType() const override {
> +    return DefinedAtom::typeCode;
> +  }
> +
> +  Alignment alignment() const override {
> +    return Alignment(2);
> +  }
> +
> +  uint64_t size() const override {
> +    return 16;
> +  }
> +
> +  ContentPermissions permissions() const override {
> +    return DefinedAtom::permR_X;
> +  }
> +
> +  ArrayRef<uint8_t> rawContent() const override {
> +    static const uint8_t bytes[] =
> +    { 0x04, 0xC0, 0x9F, 0xE5,       //  ldr ip, pc + 4
> +      0x0C, 0xC0, 0x8F, 0xE0,       //  add ip, pc, ip
> +      0x1C, 0xFF, 0x2F, 0xE1,       //  ldr pc, [ip]
> +      0x00, 0x00, 0x00, 0x00 };     //  .long target - this
> +    assert(sizeof(bytes) == size());
> +    return llvm::makeArrayRef(bytes, sizeof(bytes));
> +  }
> +private:
> +  StringRef _name;
> +};
> +
> +const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file,
> +                                               bool thumbToArm,
> +                                               const DefinedAtom &target) {
> +  bool isStub = (target.contentType() == DefinedAtom::typeStub);
> +  StringRef targetName = isStub ? stubName(target) : target.name();
> +  if (thumbToArm)
> +    return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target);
> +  else
> +    return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
> +}
> +
> +
>   std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
>     return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
>   }
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp Mon Oct 13 20:51:42 2014
> @@ -74,6 +74,10 @@ public:
>     const StubInfo &stubInfo() override { return _sStubInfo; }
>   
>     bool isCallSite(const Reference &) override;
> +  bool isNonCallBranch(const Reference &) override {
> +    return false;
> +  }
> +
>     bool isPointer(const Reference &) override;
>     bool isPairedReloc(const normalized::Relocation &) override;
>   
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86.cpp Mon Oct 13 20:51:42 2014
> @@ -34,6 +34,10 @@ public:
>   
>     const StubInfo &stubInfo() override { return _sStubInfo; }
>     bool isCallSite(const Reference &) override;
> +  bool isNonCallBranch(const Reference &) override {
> +    return false;
> +  }
> +
>     bool isPointer(const Reference &) override;
>     bool isPairedReloc(const normalized::Relocation &) override;
>   
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp Mon Oct 13 20:51:42 2014
> @@ -86,6 +86,10 @@ public:
>   
>     const StubInfo &stubInfo() override { return _sStubInfo; }
>   
> +  bool isNonCallBranch(const Reference &) override {
> +    return false;
> +  }
> +
>     bool isCallSite(const Reference &) override;
>     bool isPointer(const Reference &) override;
>     bool isPairedReloc(const normalized::Relocation &) override;
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Mon Oct 13 20:51:42 2014
> @@ -12,6 +12,7 @@ add_lld_library(lldMachO
>     MachONormalizedFileFromAtoms.cpp
>     MachONormalizedFileToAtoms.cpp
>     MachONormalizedFileYAML.cpp
> +  ShimPass.cpp
>     StubsPass.cpp
>     WriterMachO.cpp
>     )
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Mon Oct 13 20:51:42 2014
> @@ -324,6 +324,21 @@ bool MachOLinkingContext::needsCompactUn
>     }
>   }
>   
> +bool MachOLinkingContext::needsShimPass() const {
> +  // Shim pass only used in final executables.
> +  if (_outputMachOType == MH_OBJECT)
> +    return false;
> +  // Only 32-bit arm arches use Shim pass.
> +  switch (_arch) {
> +  case arch_armv6:
> +  case arch_armv7:
> +  case arch_armv7s:
> +    return true;
> +  default:
> +    return false;
> +  }
> +}
> +
>   StringRef MachOLinkingContext::binderSymbolName() const {
>     return archHandler().stubInfo().binderSymbolName;
>   }
> @@ -572,6 +587,8 @@ void MachOLinkingContext::addPasses(Pass
>       mach_o::addCompactUnwindPass(pm, *this);
>     if (needsGOTPass())
>       mach_o::addGOTPass(pm, *this);
> +  if (needsShimPass())
> +    mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
>   }
>   
>   Writer &MachOLinkingContext::writer() const {
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/MachOPasses.h Mon Oct 13 20:51:42 2014
> @@ -19,6 +19,7 @@ namespace mach_o {
>   void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx);
>   void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);
>   void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);
> +void addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
>   
>   } // namespace mach_o
>   } // namespace lld
>
> Added: lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp?rev=219655&view=auto
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp (added)
> +++ lld/trunk/lib/ReaderWriter/MachO/ShimPass.cpp Mon Oct 13 20:51:42 2014
> @@ -0,0 +1,131 @@
> +//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===//
> +//
> +//                             The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// 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/Core/DefinedAtom.h"
> +#include "lld/Core/File.h"
> +#include "lld/Core/LLVM.h"
> +#include "lld/Core/Reference.h"
> +#include "lld/Core/Simple.h"
> +#include "lld/ReaderWriter/MachOLinkingContext.h"
> +
> +#include "llvm/ADT/DenseMap.h"
> +
> +
> +namespace lld {
> +namespace mach_o {
> +
> +class ShimPass : public Pass {
> +public:
> +  ShimPass(const MachOLinkingContext &context)
> +    : _context(context)
> +    , _archHandler(_context.archHandler())
> +    , _stubInfo(_archHandler.stubInfo())
> +    , _file("<mach-o shim pass>") {
> +  }
> +
> +
> +  void perform(std::unique_ptr<MutableFile> &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;
> +
> +    // 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);
> +    }
> +  }
> +
> +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                      &_context;
> +  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::unique_ptr<Pass>(new ShimPass(ctx)));
> +}
> +
> +} // end namespace mach_o
> +} // end namespace lld
>
> Modified: lld/trunk/test/mach-o/arm-interworking.yaml
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/arm-interworking.yaml?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/test/mach-o/arm-interworking.yaml (original)
> +++ lld/trunk/test/mach-o/arm-interworking.yaml Mon Oct 13 20:51:42 2014
> @@ -237,28 +237,28 @@ undefined-symbols:
>   # CHECK:       - kind:            modeThumbCode
>   # CHECK:         offset:          0
>   # CHECK:         target:          _t1
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          0
>   # CHECK:         target:          _a1
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          6
>   # CHECK:         target:          _a2
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          12
>   # CHECK:         target:          _a2
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          16
>   # CHECK:         target:          _t1
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          22
>   # CHECK:         target:          _t1
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          28
>   # CHECK:         target:          _t2
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          34
>   # CHECK:         target:          _t2
> -# CHECK:       - kind:            thumb_b22
> +# CHECK:       - kind:            thumb_bl22
>   # CHECK:         offset:          38
>   # CHECK:         target:          _t3
>   # CHECK:   - name:            _t2
> @@ -277,16 +277,16 @@ undefined-symbols:
>   # CHECK:   - name:            _a1
>   # CHECK:     scope:           global
>   # CHECK:     references:
> -# CHECK:       - kind:            arm_b24
> +# CHECK:       - kind:            arm_bl24
>   # CHECK:         offset:          0
>   # CHECK:         target:          _a1
> -# CHECK:       - kind:            arm_b24
> +# CHECK:       - kind:            arm_bl24
>   # CHECK:         offset:          4
>   # CHECK:         target:          _a2
> -# CHECK:       - kind:            arm_b24
> +# CHECK:       - kind:            arm_bl24
>   # CHECK:         offset:          8
>   # CHECK:         target:          _t1
> -# CHECK:       - kind:            arm_b24
> +# CHECK:       - kind:            arm_bl24
>   # CHECK:         offset:          12
>   # CHECK:         target:          _t2
>   # CHECK:   - name:            _a2
>
> Added: lld/trunk/test/mach-o/arm-shims.yaml
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/arm-shims.yaml?rev=219655&view=auto
> ==============================================================================
> --- lld/trunk/test/mach-o/arm-shims.yaml (added)
> +++ lld/trunk/test/mach-o/arm-shims.yaml Mon Oct 13 20:51:42 2014
> @@ -0,0 +1,179 @@
> +# RUN: lld -flavor darwin -arch armv7 %s -dylib %p/Inputs/libSystem.yaml -o %t
> +# RUN: macho-dump --dump-section-data %t | FileCheck %s
> +#
> +# Test b from arm to thumb or vice versa has shims added.s
> +#
> +#
> +
> +--- !mach-o
> +arch:            armv7
> +file-type:       MH_OBJECT
> +flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
> +sections:
> +  - segment:         __TEXT
> +    section:         __text
> +    type:            S_REGULAR
> +    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
> +    alignment:       2
> +    address:         0x0000000000000000
> +    content:         [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
> +                       0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
> +                       0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
> +    relocations:
> +      - offset:          0x00000014
> +        type:            ARM_RELOC_BR24
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          3
> +      - offset:          0x00000010
> +        type:            ARM_RELOC_BR24
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          3
> +      - offset:          0x00000006
> +        type:            ARM_THUMB_RELOC_BR22
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          2
> +      - offset:          0x00000002
> +        type:            ARM_THUMB_RELOC_BR22
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          2
> +global-symbols:
> +  - name:            _a1
> +    type:            N_SECT
> +    scope:           [ N_EXT ]
> +    sect:            1
> +    value:           0x000000000000000C
> +  - name:            _t1
> +    type:            N_SECT
> +    scope:           [ N_EXT ]
> +    sect:            1
> +    desc:            [ N_ARM_THUMB_DEF ]
> +    value:           0x0000000000000000
> +undefined-symbols:
> +  - name:            _a2
> +    type:            N_UNDF
> +    scope:           [ N_EXT ]
> +    value:           0x0000000000000000
> +  - name:            _t2
> +    type:            N_UNDF
> +    scope:           [ N_EXT ]
> +    value:           0x0000000000000000
> +
> +
> +--- !mach-o
> +arch:            armv7
> +file-type:       MH_OBJECT
> +flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
> +sections:
> +  - segment:         __TEXT
> +    section:         __text
> +    type:            S_REGULAR
> +    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
> +    alignment:       2
> +    address:         0x0000000000000000
> +    content:         [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
> +                       0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
> +                       0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
> +    relocations:
> +      - offset:          0x00000014
> +        type:            ARM_RELOC_BR24
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          3
> +      - offset:          0x00000010
> +        type:            ARM_RELOC_BR24
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          3
> +      - offset:          0x00000006
> +        type:            ARM_THUMB_RELOC_BR22
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          2
> +      - offset:          0x00000002
> +        type:            ARM_THUMB_RELOC_BR22
> +        length:          2
> +        pc-rel:          true
> +        extern:          true
> +        symbol:          2
> +global-symbols:
> +  - name:            _a2
> +    type:            N_SECT
> +    scope:           [ N_EXT ]
> +    sect:            1
> +    value:           0x000000000000000C
> +  - name:            _t2
> +    type:            N_SECT
> +    scope:           [ N_EXT ]
> +    sect:            1
> +    desc:            [ N_ARM_THUMB_DEF ]
> +    value:           0x0000000000000000
> +undefined-symbols:
> +  - name:            _a1
> +    type:            N_UNDF
> +    scope:           [ N_EXT ]
> +    value:           0x0000000000000000
> +  - name:            _t1
> +    type:            N_UNDF
> +    scope:           [ N_EXT ]
> +    value:           0x0000000000000000
> +
> +...
> +
> +
> +# CHECK:    (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
> +# CHECK:     ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
> +# CHECK:     ('_section_data', '00bf00f0 10e800f0 19b80000 00f020e3 000000fa 0f0000ea 00bffff7 f8ef00f0 07b80000 00f020e3 f4fffffa 050000ea dff804c0 ff446047 d4ffffff dff804c0 ff446047 e0ffffff 04c09fe5 0cc08fe0 1cff2fe1 adffffff 04c09fe5 0cc08fe0 1cff2fe1 b5ffffff')
> +
> +# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
> +
> +
> +# Input file one:
> +#
> +#	.align	2
> +#	.code	16
> +#  .globl _t1
> +#  .thumb_func	_t1
> +#_t1:
> +#    nop
> +#    blx _a2
> +#    b   _a2
> +#
> +#	.code	32
> +#  .align 2
> +#  .globl _a1
> +#_a1:
> +#    nop
> +#    blx _t2
> +#    b   _t2
> +
> +
> +
> +# Input file two:
> +#
> +#	.align	2
> +#	.code	16
> +#  .globl _t2
> +#  .thumb_func	_t2
> +#_t2:
> +#    nop
> +#    blx _a1
> +#    b   _a1
> +#
> +#	.code	32
> +#  .align 2
> +#  .globl _a2
> +#_a2:
> +#    nop
> +#    blx _t1
> +#    b   _t1
>
> Modified: lld/trunk/test/mach-o/parse-arm-relocs.yaml
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/parse-arm-relocs.yaml?rev=219655&r1=219654&r2=219655&view=diff
> ==============================================================================
> --- lld/trunk/test/mach-o/parse-arm-relocs.yaml (original)
> +++ lld/trunk/test/mach-o/parse-arm-relocs.yaml Mon Oct 13 20:51:42 2014
> @@ -572,19 +572,19 @@ undefined-symbols:
>   # CHECK:      references:
>   # CHECK:        - kind:            modeThumbCode
>   # CHECK:          offset:          0
> -# CHECK:        - kind:            thumb_b22
> +# CHECK:        - kind:            thumb_bl22
>   # CHECK:          offset:          0
>   # CHECK:          target:          _x
>   # CHECK-NOT:      addend:
> -# CHECK:        - kind:            thumb_b22
> +# CHECK:        - kind:            thumb_bl22
>   # CHECK:          offset:          4
>   # CHECK:          target:          _x
>   # CHECK:          addend:          4
> -# CHECK:        - kind:            thumb_b22
> +# CHECK:        - kind:            thumb_bl22
>   # CHECK:          offset:          8
>   # CHECK:          target:          _undef
>   # CHECK-NOT:      addend:
> -# CHECK:        - kind:            thumb_b22
> +# CHECK:        - kind:            thumb_bl22
>   # CHECK:          offset:          12
>   # CHECK:          target:          _undef
>   # CHECK:          addend:          4
> @@ -660,19 +660,19 @@ undefined-symbols:
>   # CHECK:    - name:            _foo_arm
>   # CHECK:      references:
>   # CHECK-NOT:    - kind:            modeThumbCode
> -# CHECK:        - kind:            arm_b24
> +# CHECK:        - kind:            arm_bl24
>   # CHECK:          offset:          0
>   # CHECK:          target:          _x
>   # CHECK-NOT:      addend:
> -# CHECK:        - kind:            arm_b24
> +# CHECK:        - kind:            arm_bl24
>   # CHECK:          offset:          4
>   # CHECK:          target:          _x
>   # CHECK:          addend:          4
> -# CHECK:        - kind:            arm_b24
> +# CHECK:        - kind:            arm_bl24
>   # CHECK:          offset:          8
>   # CHECK:          target:          _undef
>   # CHECK-NOT:      addend:
> -# CHECK:        - kind:            arm_b24
> +# CHECK:        - kind:            arm_bl24
>   # CHECK:          offset:          12
>   # CHECK:          target:          _undef
>   # CHECK:          addend:          4
> @@ -739,11 +739,11 @@ undefined-symbols:
>   #  bl    _undef
>   #  bl    _undef+4
>   #  movw	r1, :lower16:(_x-L1)
> -# 	movt	r1, :upper16:(_x-L1)
> +#  movt	r1, :upper16:(_x-L1)
>   #  movw	r2, :lower16:(_x+8-L1)
> -# 	movt	r2, :upper16:(_x+8-L1)
> +#  movt	r2, :upper16:(_x+8-L1)
>   #  movw	r1, :lower16:(_t1-L1)
> -# 	movt	r1, :upper16:(_t1-L1)
> +#  movt	r1, :upper16:(_t1-L1)
>   #	add	r1, pc
>   #L1:
>   #	movw	r3, :lower16:_x
> @@ -770,9 +770,9 @@ undefined-symbols:
>   #  bl    _undef
>   #  bl    _undef+4
>   #  movw	r1, :lower16:(_x-L2)
> -# 	movt	r1, :upper16:(_x-L2)
> +#  movt	r1, :upper16:(_x-L2)
>   #  movw	r2, :lower16:(_x+8-L2)
> -# 	movt	r2, :upper16:(_x+8-L2)
> +#  movt	r2, :upper16:(_x+8-L2)
>   #	add	r1, pc
>   #L2:
>   #	movw	r3, :lower16:_x
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation




More information about the llvm-commits mailing list