[lld] r213712 - [mach-o] add initial support for modes in arm code.

Nick Kledzik kledzik at apple.com
Tue Jul 22 17:51:38 PDT 2014


Author: kledzik
Date: Tue Jul 22 19:51:37 2014
New Revision: 213712

URL: http://llvm.org/viewvc/llvm-project?rev=213712&view=rev
Log:
[mach-o] add initial support for modes in arm code.

This patch just supports marking ranges that are thumb code (vs arm code).
Future patches will mark data and jump table ranges. The ranges are encoded
as References with offsetInAtom being the start of the range and the target
being the same atom.

Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/test/mach-o/parse-arm-relocs.yaml

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h?rev=213712&r1=213711&r2=213712&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler.h Tue Jul 22 19:51:37 2014
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "MachONormalizedFile.h"
+#include "Atoms.h"
 
 #include "lld/Core/LLVM.h"
 #include "lld/Core/Reference.h"
@@ -136,6 +137,11 @@ public:
                                         FindAddressForAtom,
                                         normalized::Relocations&) = 0;
 
+  /// Add arch-specific References.
+  virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
+
+  /// Only relevant for 32-bit arm archs.
+  virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
 
   struct ReferenceInfo {
     Reference::KindArch arch;

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=213712&r1=213711&r2=213712&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Tue Jul 22 19:51:37 2014
@@ -69,6 +69,9 @@ public:
                                 FindAddressForAtom,
                                 normalized::Relocations &) override;
 
+  void addAdditionalReferences(MachODefinedAtom &atom) override;
+
+  bool isThumbFunction(const DefinedAtom &atom) override;
 
 private:
   static const Registry::KindStrings _sKindStrings[];
@@ -77,6 +80,9 @@ private:
   enum : Reference::KindValue {
     invalid,               /// for error condition
 
+    modeThumbCode,         /// Content starting at this offset is thumb.
+    modeArmCode,           /// Content starting at this offset is arm.
+
     // Kinds found in mach-o .o files:
     thumb_b22,             /// ex: bl _foo
     thumb_movw,            /// ex: movw	r1, :lower16:_foo
@@ -115,12 +121,12 @@ private:
 
   void applyFixupFinal(const Reference &ref, uint8_t *location,
                        uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress);
+                       uint64_t inAtomAddress, bool &thumbMode);
 
   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
                              uint64_t fixupAddress,
                              uint64_t targetAddress,
-                             uint64_t inAtomAddress);
+                             uint64_t inAtomAddress, bool &thumbMode);
   
   const bool _swap;
 };
@@ -135,6 +141,8 @@ ArchHandler_arm::ArchHandler_arm() :
 ArchHandler_arm::~ArchHandler_arm() { }
 
 const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = {
+  LLD_KIND_STRING_ENTRY(modeThumbCode),
+  LLD_KIND_STRING_ENTRY(modeArmCode),
   LLD_KIND_STRING_ENTRY(thumb_b22),
   LLD_KIND_STRING_ENTRY(thumb_movw),
   LLD_KIND_STRING_ENTRY(thumb_movt),
@@ -712,7 +720,8 @@ ArchHandler_arm::getPairReferenceInfo(co
 void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *location,
                                       uint64_t fixupAddress,
                                       uint64_t targetAddress,
-                                      uint64_t inAtomAddress) {
+                                      uint64_t inAtomAddress,
+                                      bool &thumbMode) {
   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
   assert(ref.kindArch() == Reference::KindArch::ARM);
@@ -720,43 +729,59 @@ void ArchHandler_arm::applyFixupFinal(co
   int32_t displacement;
   uint16_t value16;
   switch (ref.kindValue()) {
+  case modeThumbCode:
+    thumbMode = true;
+    break;
+  case modeArmCode:
+    thumbMode = false;
+    break;
   case thumb_b22:
+    assert(thumbMode);
     displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
     write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement));
     break;
   case thumb_movw:
+    assert(thumbMode);
     value16 = (targetAddress + ref.addend()) & 0xFFFF;
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case thumb_movt:
+    assert(thumbMode);
     value16 = (targetAddress + ref.addend()) >> 16;
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case thumb_movw_funcRel:
+    assert(thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case thumb_movt_funcRel:
+    assert(thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case arm_b24:
+    assert(!thumbMode);
     displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
     *loc32 = setDisplacementInArmBranch(*loc32, displacement);
     break;
   case arm_movw:
+    assert(!thumbMode);
     value16 = (targetAddress + ref.addend()) & 0xFFFF;
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case arm_movt:
+    assert(!thumbMode);
     value16 = (targetAddress + ref.addend()) >> 16;
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case arm_movw_funcRel:
+    assert(!thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case arm_movt_funcRel:
+    assert(!thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
@@ -783,6 +808,7 @@ void ArchHandler_arm::generateAtomConten
   // Copy raw bytes.
   memcpy(atomContentBuffer, atom.rawContent().data(), atom.size());
   // Apply fix-ups.
+  bool thumbMode = false;
   for (const Reference *ref : atom) {
     uint32_t offset = ref->offsetInAtom();
     const Atom *target = ref->target();
@@ -794,11 +820,11 @@ void ArchHandler_arm::generateAtomConten
     if (relocatable) {
       applyFixupRelocatable(*ref, &atomContentBuffer[offset],
                                         fixupAddress, targetAddress,
-                                        atomAddress);
+                                        atomAddress, thumbMode);
     } else {
       applyFixupFinal(*ref, &atomContentBuffer[offset],
                                   fixupAddress, targetAddress,
-                                  atomAddress);
+                                  atomAddress, thumbMode);
     }
   }
 }
@@ -829,13 +855,21 @@ void ArchHandler_arm::applyFixupRelocata
                                              uint8_t *location,
                                              uint64_t fixupAddress,
                                              uint64_t targetAddress,
-                                             uint64_t inAtomAddress)  {
+                                             uint64_t inAtomAddress,
+                                             bool &thumbMode) {
   bool useExternalReloc = useExternalRelocationTo(*ref.target());
   int32_t *loc32 = reinterpret_cast<int32_t *>(location);
   int32_t displacement;
   uint16_t value16;
   switch (ref.kindValue()) {
+  case modeThumbCode:
+    thumbMode = true;
+    break;
+  case modeArmCode:
+    thumbMode = false;
+    break;
   case thumb_b22:
+    assert(thumbMode);
     if (useExternalReloc)
       displacement = (ref.addend() - (fixupAddress + 4));
     else
@@ -843,6 +877,7 @@ void ArchHandler_arm::applyFixupRelocata
     write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement));
     break;
   case thumb_movw:
+    assert(thumbMode);
     if (useExternalReloc)
       value16 = ref.addend() & 0xFFFF;
     else
@@ -850,6 +885,7 @@ void ArchHandler_arm::applyFixupRelocata
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case thumb_movt:
+    assert(thumbMode);
     if (useExternalReloc)
       value16 = ref.addend() >> 16;
     else
@@ -857,14 +893,17 @@ void ArchHandler_arm::applyFixupRelocata
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case thumb_movw_funcRel:
+    assert(thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case thumb_movt_funcRel:
+    assert(thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
     write32(*loc32, _swap, setWordFromThumbMov(*loc32, value16));
     break;
   case arm_b24:
+    assert(!thumbMode);
     if (useExternalReloc)
       displacement = (ref.addend() - (fixupAddress + 8));
     else
@@ -872,6 +911,7 @@ void ArchHandler_arm::applyFixupRelocata
     write32(*loc32, _swap, setDisplacementInArmBranch(*loc32, displacement));
     break;
   case arm_movw:
+    assert(!thumbMode);
     if (useExternalReloc)
       value16 = ref.addend() & 0xFFFF;
     else
@@ -879,6 +919,7 @@ void ArchHandler_arm::applyFixupRelocata
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case arm_movt:
+    assert(!thumbMode);
     if (useExternalReloc)
       value16 = ref.addend() >> 16;
     else
@@ -886,10 +927,12 @@ void ArchHandler_arm::applyFixupRelocata
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case arm_movw_funcRel:
+    assert(!thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case arm_movt_funcRel:
+    assert(!thumbMode);
     value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
@@ -926,6 +969,10 @@ void ArchHandler_arm::appendSectionReloc
   uint32_t fromAtomAddress;
   uint16_t other16;
   switch (ref.kindValue()) {
+  case modeThumbCode:
+  case modeArmCode:
+    // Do nothing.
+    break;
   case thumb_b22:
     if (useExternalReloc) {
       appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
@@ -1115,6 +1162,25 @@ void ArchHandler_arm::appendSectionReloc
   }
 }
 
+void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
+  if (atom.isThumb()) {
+    atom.addReference(0, modeThumbCode, &atom, 0, Reference::KindArch::ARM);
+  }
+}
+
+bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
+  for (const Reference *ref : atom) {
+    if (ref->offsetInAtom() != 0)
+      return false;
+    if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
+      continue;
+     assert(ref->kindArch() == Reference::KindArch::ARM);
+    if (ref->kindValue() == modeThumbCode)
+      return true;
+  }
+  return false;
+}
+
 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/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=213712&r1=213711&r2=213712&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Tue Jul 22 19:51:37 2014
@@ -139,6 +139,16 @@ public:
     return pos->second;
   }
   
+  typedef std::function<void (MachODefinedAtom* atom)> DefinedAtomVisitor;
+
+  void eachDefinedAtom(DefinedAtomVisitor vistor) {
+    for (auto &sectAndAtoms : _sectionAtoms) {
+      for (auto &offAndAtom : sectAndAtoms.second) {
+        vistor(offAndAtom.atom);
+      }
+    }
+  }
+
   llvm::BumpPtrAllocator &allocator() { return _allocator; }
   
 private:

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=213712&r1=213711&r2=213712&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Tue Jul 22 19:51:37 2014
@@ -617,6 +617,8 @@ uint16_t Util::descBits(const DefinedAto
   }
   if (atom->contentType() == lld::DefinedAtom::typeResolver)
     desc |= N_SYMBOL_RESOLVER;
+  if (_archHandler.isThumbFunction(*atom))
+    desc |= N_ARM_THUMB_DEF;
   return desc;
 }
 
@@ -656,7 +658,7 @@ void Util::addSymbols(const lld::File &a
           sym.type  = N_SECT;
           sym.scope = scopeBits(atom);
           sym.sect  = sect->finalSectionIndex;
-          sym.desc  = 0;
+          sym.desc  = descBits(atom);
           sym.value = _atomToAddress[atom];
           _atomToSymbolIndex[atom] = file.localSymbols.size();
           file.localSymbols.push_back(sym);

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=213712&r1=213711&r2=213712&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Tue Jul 22 19:51:37 2014
@@ -562,6 +562,7 @@ std::error_code convertRelocs(const Sect
                            handler.kindArch());
     }
   }
+
   return std::error_code();
 }
 
@@ -606,6 +607,11 @@ normalizedObjectToAtoms(const Normalized
         return ec;
   }
 
+  // Add additional arch-specific References
+  file->eachDefinedAtom([&](MachODefinedAtom* atom) -> void {
+    handler->addAdditionalReferences(*atom);
+  });
+
   // Sort references in each atom to their canonical order.
   for (const DefinedAtom* defAtom : file->defined()) {
     reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();

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=213712&r1=213711&r2=213712&view=diff
==============================================================================
--- lld/trunk/test/mach-o/parse-arm-relocs.yaml (original)
+++ lld/trunk/test/mach-o/parse-arm-relocs.yaml Tue Jul 22 19:51:37 2014
@@ -570,6 +570,8 @@ undefined-symbols:
 # CHECK:          addend:          4
 # CHECK:    - name:            _foo_thumb
 # CHECK:      references:
+# CHECK:        - kind:            modeThumbCode
+# CHECK:          offset:          0
 # CHECK:        - kind:            thumb_b22
 # CHECK:          offset:          0
 # CHECK:          target:          _x
@@ -652,8 +654,12 @@ undefined-symbols:
 # CHECK:          addend:          8
 # CHECK:    - name:            _t1
 # CHECK:      content:         [ C0, 46 ]
+# CHECK:      references:
+# CHECK:        - kind:            modeThumbCode
+# CHECK:          offset:          0
 # CHECK:    - name:            _foo_arm
 # CHECK:      references:
+# CHECK-NOT:    - kind:            modeThumbCode
 # CHECK:        - kind:            arm_b24
 # CHECK:          offset:          0
 # CHECK:          target:          _x





More information about the llvm-commits mailing list