[lld] r214140 - [mach-o] Implement interworking between thumb and arm code

Nick Kledzik kledzik at apple.com
Mon Jul 28 16:06:09 PDT 2014


Author: kledzik
Date: Mon Jul 28 18:06:09 2014
New Revision: 214140

URL: http://llvm.org/viewvc/llvm-project?rev=214140&view=rev
Log:
[mach-o] Implement interworking between thumb and arm code

All iOS arm processor support switching between arm and thumb mode at call sites
by using the BLX instruction (instead of BL).  But the compiler does not know
the implementation mode for extern functions, so the linker must update BL/BLX
instructions to match what is linked is actually linked together.  In addition,
pointers to functions (such as vtables) must have the low bit set if the target
of the pointer is a thumb mode function.

Added:
    lld/trunk/test/mach-o/arm-interworking.yaml
    lld/trunk/test/mach-o/hello-world-armv7.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp

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=214140&r1=214139&r2=214140&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Mon Jul 28 18:06:09 2014
@@ -130,13 +130,15 @@ private:
   static bool isThumbMovt(uint32_t instruction);
   static bool isArmMovw(uint32_t instruction);
   static bool isArmMovt(uint32_t instruction);
-  static int32_t getDisplacementFromThumbBranch(uint32_t instruction);
+  static int32_t getDisplacementFromThumbBranch(uint32_t instruction, uint32_t);
   static int32_t getDisplacementFromArmBranch(uint32_t instruction);
   static uint16_t getWordFromThumbMov(uint32_t instruction);
   static uint16_t getWordFromArmMov(uint32_t instruction);
   static uint32_t clearThumbBit(uint32_t value, const Atom *target);
-  static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp);
-  static uint32_t setDisplacementInThumbBranch(uint32_t instr, int32_t disp);
+  static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp, 
+                                             bool targetIsThumb);
+  static uint32_t setDisplacementInThumbBranch(uint32_t instr, uint32_t ia,
+                                               int32_t disp, bool targetThumb);
   static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word);
   static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word);
   
@@ -144,12 +146,14 @@ private:
 
   void applyFixupFinal(const Reference &ref, uint8_t *location,
                        uint64_t fixupAddress, uint64_t targetAddress,
-                       uint64_t inAtomAddress, bool &thumbMode);
+                       uint64_t inAtomAddress, bool &thumbMode,
+                       bool targetIsThumb);
 
   void applyFixupRelocatable(const Reference &ref, uint8_t *location,
                              uint64_t fixupAddress,
                              uint64_t targetAddress,
-                             uint64_t inAtomAddress, bool &thumbMode);
+                             uint64_t inAtomAddress, bool &thumbMode,
+                             bool targetIsThumb);
   
   const bool _swap;
 };
@@ -256,23 +260,7 @@ bool ArchHandler_arm::isPairedReloc(cons
   }
 }
 
-int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction) {
-  uint32_t s = (instruction >> 10) & 0x1;
-  uint32_t j1 = (instruction >> 29) & 0x1;
-  uint32_t j2 = (instruction >> 27) & 0x1;
-  uint32_t imm10 = instruction & 0x3FF;
-  uint32_t imm11 = (instruction >> 16) & 0x7FF;
-  uint32_t i1 = (j1 == s);
-  uint32_t i2 = (j2 == s);
-  uint32_t dis =
-      (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
-  int32_t sdis = dis;
-  if (s)
-    return (sdis | 0xFE000000);
-  else
-    return sdis;
-}
-
+/// Extract displacement from an ARM b/bl/blx instruction.
 int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
   // Sign-extend imm24
   int32_t displacement = (instruction & 0x00FFFFFF) << 2;
@@ -284,18 +272,88 @@ int32_t ArchHandler_arm::getDisplacement
   return displacement;
 }
 
+/// Update an ARM b/bl/blx instruction, switching bl <-> blx as needed.
 uint32_t ArchHandler_arm::setDisplacementInArmBranch(uint32_t instruction,
-                                                     int32_t displacement) {
-  // FIXME: handle BLX and out-of-range.
+                                                     int32_t displacement,
+                                                     bool targetIsThumb) {
+  assert((displacement <= 33554428) && (displacement > (-33554432))
+                                              && "arm branch out of range");
+  bool is_blx = ((instruction & 0xF0000000) == 0xF0000000);
   uint32_t newInstruction = (instruction & 0xFF000000);
-  newInstruction |= ((displacement >> 2) & 0x00FFFFFF);
+  uint32_t h = 0;
+  if (targetIsThumb) {
+    // Force use of BLX.
+    newInstruction = 0xFA000000;
+    if (!is_blx) {
+      bool isConditionalBranch = ((instruction & 0xF0000000) != 0xE0000000);
+      assert(!isConditionalBranch && "no conditional arm blx");
+      bool is_bl = ((instruction & 0xFF000000) == 0xEB000000);
+      assert(is_bl && "no arm pc-rel BX instruction");
+    }
+    if (displacement & 2)
+      h = 1;
+  }
+  else {
+    // Force use of B/BL.
+    if (is_blx)
+      newInstruction = 0xEB000000;
+  }
+  newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF);
   return newInstruction;
 }
 
+/// Extract displacement from a thumb b/bl/blx instruction.
+int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction,
+                                                        uint32_t instrAddr) {
+  bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
+  uint32_t s = (instruction >> 10) & 0x1;
+  uint32_t j1 = (instruction >> 29) & 0x1;
+  uint32_t j2 = (instruction >> 27) & 0x1;
+  uint32_t imm10 = instruction & 0x3FF;
+  uint32_t imm11 = (instruction >> 16) & 0x7FF;
+  uint32_t i1 = (j1 == s);
+  uint32_t i2 = (j2 == s);
+  uint32_t dis =
+      (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
+  int32_t sdis = dis;
+  int32_t result = s ? (sdis | 0xFE000000) : sdis;
+  if (is_blx && (instrAddr & 0x2)) {
+    // The thumb blx instruction always has low bit of imm11 as zero.  The way
+    // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that
+    // the blx instruction always 4-byte aligns the pc before adding the
+    // displacement from the blx.  We must emulate that when decoding this.
+    result -= 2;
+  }
+  return result;
+}
+
+/// Update a thumb b/bl/blx instruction, switching bl <-> blx as needed.
 uint32_t ArchHandler_arm::setDisplacementInThumbBranch(uint32_t instruction,
-                                                       int32_t displacement) {
-  // FIXME: handle BLX and out-of-range.
+                                                       uint32_t instrAddr,
+                                                       int32_t displacement,
+                                                       bool targetIsThumb) {
+  assert((displacement <= 16777214) && (displacement > (-16777216))
+                                              && "thumb branch out of range");
+	bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
+	bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
+	bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
   uint32_t newInstruction = (instruction & 0xF800D000);
+  if (is_bl || is_blx) {
+    if (targetIsThumb) {
+      newInstruction = 0xD000F000; // Use bl
+    } else {
+      newInstruction = 0xC000F000; // Use blx
+      // See note in getDisplacementFromThumbBranch() about blx.
+      if (instrAddr & 0x2)
+        displacement += 2;
+    }
+  } else if (is_b) {
+    assert(!targetIsThumb && "no pc-rel thumb branch instruction that "
+                             "switches to arm mode");
+  }
+  else {
+    llvm_unreachable("thumb branch22 reloc on a non-branch instruction");
+  }
   uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
   uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
   uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
@@ -392,19 +450,19 @@ std::error_code ArchHandler_arm::getRefe
     if (E ec = atomFromSymbolIndex(reloc.symbol, target))
       return ec;
     // Instruction contains branch to addend.
-    displacement = getDisplacementFromThumbBranch(instruction);
+    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
     *addend = fixupAddress + 4 + displacement;
     return std::error_code();
   case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
     // ex: bl _foo (and _foo is defined)
     *kind = thumb_b22;
-    displacement = getDisplacementFromThumbBranch(instruction);
+    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;
-    displacement = getDisplacementFromThumbBranch(instruction);
+    displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
     targetAddress = fixupAddress + 4 + displacement;
     if (E ec = atomFromAddress(0, reloc.value, target, addend))
       return ec;
@@ -745,13 +803,14 @@ void ArchHandler_arm::applyFixupFinal(co
                                       uint64_t fixupAddress,
                                       uint64_t targetAddress,
                                       uint64_t inAtomAddress,
-                                      bool &thumbMode) {
+                                      bool &thumbMode, bool targetIsThumb) {
   if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
     return;
   assert(ref.kindArch() == Reference::KindArch::ARM);
   int32_t *loc32 = reinterpret_cast<int32_t *>(location);
   int32_t displacement;
   uint16_t value16;
+  uint32_t value32;
   switch (ref.kindValue()) {
   case modeThumbCode:
     thumbMode = true;
@@ -764,7 +823,9 @@ void ArchHandler_arm::applyFixupFinal(co
   case thumb_b22:
     assert(thumbMode);
     displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
-    write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement));
+    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement,
+                                           targetIsThumb);
+    write32(*loc32, _swap, value32);
     break;
   case thumb_movw:
     assert(thumbMode);
@@ -789,7 +850,8 @@ void ArchHandler_arm::applyFixupFinal(co
   case arm_b24:
     assert(!thumbMode);
     displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
-    *loc32 = setDisplacementInArmBranch(*loc32, displacement);
+    value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
+    write32(*loc32, _swap, value32);
     break;
   case arm_movw:
     assert(!thumbMode);
@@ -812,7 +874,10 @@ void ArchHandler_arm::applyFixupFinal(co
     write32(*loc32, _swap, setWordFromArmMov(*loc32, value16));
     break;
   case pointer32:
-    write32(*loc32, _swap, targetAddress + ref.addend());
+    if (targetIsThumb)
+      write32(*loc32, _swap, targetAddress + ref.addend() + 1);
+    else
+      write32(*loc32, _swap, targetAddress + ref.addend());
     break;
   case delta32:
     write32(*loc32, _swap, targetAddress - fixupAddress + ref.addend());
@@ -839,18 +904,20 @@ void ArchHandler_arm::generateAtomConten
     uint32_t offset = ref->offsetInAtom();
     const Atom *target = ref->target();
     uint64_t targetAddress = 0;
-    if (isa<DefinedAtom>(target))
+    bool targetIsThumb = false;
+    if (const DefinedAtom *defTarg = dyn_cast<DefinedAtom>(target)) {
       targetAddress = findAddress(*target);
+      targetIsThumb = isThumbFunction(*defTarg);
+    }
     uint64_t atomAddress = findAddress(atom);
     uint64_t fixupAddress = atomAddress + offset;
     if (relocatable) {
-      applyFixupRelocatable(*ref, &atomContentBuffer[offset],
-                                        fixupAddress, targetAddress,
-                                        atomAddress, thumbMode);
+      applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
+                            targetAddress, atomAddress, thumbMode,
+                            targetIsThumb);
     } else {
-      applyFixupFinal(*ref, &atomContentBuffer[offset],
-                                  fixupAddress, targetAddress,
-                                  atomAddress, thumbMode);
+      applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
+                      targetAddress, atomAddress, thumbMode, targetIsThumb);
     }
   }
 }
@@ -882,11 +949,13 @@ void ArchHandler_arm::applyFixupRelocata
                                              uint64_t fixupAddress,
                                              uint64_t targetAddress,
                                              uint64_t inAtomAddress,
-                                             bool &thumbMode) {
+                                             bool &thumbMode,
+                                             bool targetIsThumb) {
   bool useExternalReloc = useExternalRelocationTo(*ref.target());
   int32_t *loc32 = reinterpret_cast<int32_t *>(location);
   int32_t displacement;
   uint16_t value16;
+  uint32_t value32;
   switch (ref.kindValue()) {
   case modeThumbCode:
     thumbMode = true;
@@ -902,7 +971,9 @@ void ArchHandler_arm::applyFixupRelocata
       displacement = (ref.addend() - (fixupAddress + 4));
     else
       displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
-    write32(*loc32, _swap, setDisplacementInThumbBranch(*loc32, displacement));
+    value32 = setDisplacementInThumbBranch(*loc32, fixupAddress, displacement,
+                                           targetIsThumb);
+    write32(*loc32, _swap, value32);
     break;
   case thumb_movw:
     assert(thumbMode);
@@ -936,7 +1007,8 @@ void ArchHandler_arm::applyFixupRelocata
       displacement = (ref.addend() - (fixupAddress + 8));
     else
       displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
-    write32(*loc32, _swap, setDisplacementInArmBranch(*loc32, displacement));
+    value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
+    write32(*loc32, _swap, value32);
     break;
   case arm_movw:
     assert(!thumbMode);

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=214140&r1=214139&r2=214140&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Mon Jul 28 18:06:09 2014
@@ -563,7 +563,10 @@ void Util::copySections(NormalizedFile &
 
 void Util::copyEntryPointAddress(NormalizedFile &nFile) {
   if (_context.outputTypeHasEntry()) {
-    nFile.entryAddress = _atomToAddress[_entryAtom];
+    if (_archHandler.isThumbFunction(*_entryAtom))
+      nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
+    else
+      nFile.entryAddress = _atomToAddress[_entryAtom];
   }
 }
 

Added: lld/trunk/test/mach-o/arm-interworking.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/arm-interworking.yaml?rev=214140&view=auto
==============================================================================
--- lld/trunk/test/mach-o/arm-interworking.yaml (added)
+++ lld/trunk/test/mach-o/arm-interworking.yaml Mon Jul 28 18:06:09 2014
@@ -0,0 +1,361 @@
+# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s -o %t  | FileCheck %s \
+# RUN: && lld -flavor darwin -arch armv7 -dylib -print_atoms %t -o %t2  | FileCheck %s \
+# RUN: && macho-dump --dump-section-data %t2 | FileCheck -check-prefix=CODE %s 
+#
+# Test thumb and arm branches round trip through -r.
+# Test bl/blx instructions are fixed up properly.
+#
+#
+
+--- !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:         [ 0xFF, 0xF7, 0xFE, 0xFF, 0xC0, 0x46, 0xFF, 0xF7, 
+                       0xFC, 0xEF, 0xC0, 0x46, 0xFF, 0xF7, 0xF8, 0xEF, 
+                       0xFF, 0xF7, 0xF6, 0xFF, 0xC0, 0x46, 0xFF, 0xF7, 
+                       0xF3, 0xFF, 0xC0, 0x46, 0x00, 0xF0, 0x06, 0xE8, 
+                       0xC0, 0x46, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xF0, 
+                       0x02, 0xF8, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47 ]
+    relocations:     
+      - offset:          0x00000026
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+      - offset:          0x00000022
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+      - offset:          0x0000001C
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+      - offset:          0x00000016
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+      - offset:          0x00000010
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+      - offset:          0x0000000C
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          5
+      - offset:          0x00000006
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          5
+      - offset:          0x00000000
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    address:         0x0000000000000030
+    content:         [ 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:     
+      - offset:          0x00000004
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          4
+      - offset:          0x00000000
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+local-symbols:   
+  - name:            _t3
+    type:            N_SECT
+    sect:            1
+    desc:            [ N_ARM_THUMB_DEF ]
+    value:           0x000000000000002E
+  - name:            _d1
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000030
+global-symbols:  
+  - name:            _t1
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    desc:            [ N_ARM_THUMB_DEF ]
+    value:           0x0000000000000000
+  - name:            _t2
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    desc:            [ N_ARM_THUMB_DEF ]
+    value:           0x000000000000002C
+undefined-symbols: 
+  - name:            _a1
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            _a2
+    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:         [ 0xFE, 0xFF, 0xFF, 0xEB, 0x02, 0x00, 0x00, 0xFA, 
+                       0xFC, 0xFF, 0xFF, 0xEB, 0xFB, 0xFF, 0xFF, 0xFA, 
+                       0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1 ]
+    relocations:     
+      - offset:          0x0000000C
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          4
+      - offset:          0x00000008
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          3
+      - offset:          0x00000004
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+      - offset:          0x00000000
+        type:            ARM_RELOC_BR24
+        length:          2
+        pc-rel:          true
+        extern:          false
+        symbol:          1
+  - segment:         __DATA
+    section:         __data
+    type:            S_REGULAR
+    attributes:      [  ]
+    address:         0x0000000000000018
+    content:         [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+    relocations:     
+      - offset:          0x00000004
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          false
+        symbol:          1
+      - offset:          0x00000000
+        type:            ARM_RELOC_VANILLA
+        length:          2
+        pc-rel:          false
+        extern:          true
+        symbol:          3
+local-symbols:   
+  - name:            _d2
+    type:            N_SECT
+    sect:            2
+    value:           0x0000000000000018
+global-symbols:  
+  - name:            _a1
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000000
+  - name:            _a2
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000014
+undefined-symbols: 
+  - name:            _t1
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+  - name:            _t2
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+
+
+# CHECK: defined-atoms:   
+# CHECK:   - name:            _d1
+# CHECK:     type:            data
+# CHECK:     references:      
+# CHECK:       - kind:            pointer32
+# CHECK:         offset:          0
+# CHECK:         target:          _t2
+# CHECK:       - kind:            pointer32
+# CHECK:         offset:          4
+# CHECK:         target:          _a1
+# CHECK:   - name:            _d2
+# CHECK:     type:            data
+# CHECK:     references:      
+# CHECK:       - kind:            pointer32
+# CHECK:         offset:          0
+# CHECK:         target:          _t1
+# CHECK:       - kind:            pointer32
+# CHECK:         offset:          4
+# CHECK:         target:          _a1
+# CHECK:   - name:            _t1
+# CHECK:     scope:           global
+# CHECK:     references:      
+# CHECK:       - kind:            modeThumbCode
+# CHECK:         offset:          0
+# CHECK:         target:          _t1
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          0
+# CHECK:         target:          _a1
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          6
+# CHECK:         target:          _a2
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          12
+# CHECK:         target:          _a2
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          16
+# CHECK:         target:          _t1
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          22
+# CHECK:         target:          _t1
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          28
+# CHECK:         target:          _t2
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          34
+# CHECK:         target:          _t2
+# CHECK:       - kind:            thumb_b22
+# CHECK:         offset:          38
+# CHECK:         target:          _t3
+# CHECK:   - name:            _t2
+# CHECK:     scope:           global
+# CHECK:     content:         [ 70, 47 ]
+# CHECK:     references:      
+# CHECK:       - kind:            modeThumbCode
+# CHECK:         offset:          0
+# CHECK:         target:          _t2
+# CHECK:   - name:            _t3
+# CHECK:     content:         [ 70, 47 ]
+# CHECK:     references:      
+# CHECK:       - kind:            modeThumbCode
+# CHECK:         offset:          0
+# CHECK:         target:          _t3
+# CHECK:   - name:            _a1
+# CHECK:     scope:           global
+# CHECK:     references:      
+# CHECK:       - kind:            arm_b24
+# CHECK:         offset:          0
+# CHECK:         target:          _a1
+# CHECK:       - kind:            arm_b24
+# CHECK:         offset:          4
+# CHECK:         target:          _a2
+# CHECK:       - kind:            arm_b24
+# CHECK:         offset:          8
+# CHECK:         target:          _t1
+# CHECK:       - kind:            arm_b24
+# CHECK:         offset:          12
+# CHECK:         target:          _t2
+# CHECK:   - name:            _a2
+# CHECK:     scope:           global
+
+
+# CODE:    (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+# CODE:     ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+# CODE:   ('_section_data', '00f016e8 c04600f0 1ee8c046 00f01ae8 fff7f6ff c046fff7 f3ffc046 00f006f8 c04600f0 03f800f0 02f87047 70477047 feffffeb 020000eb f0fffffa fafffffa 1eff2fe1 1eff2fe1')
+# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
+
+# CODE:  (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+# CODE:    ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+# CODE:  ('_section_data', '{{[0-9a-f]}}{{[13579bdf]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[02468ade]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[13579bdf]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[02468ade]}}{{[0-9a-f]+}}')
+# Verify the low (thumb) bit is set on the first and third pointers but not the second and fourth.
+
+
+
+# Input file one:
+#
+#	.align	2
+#	.code	16
+#  .globl _t1
+#  .thumb_func	_t1
+#_t1:
+#    bl  _a1
+#    nop
+#    blx _a2
+#    nop
+#    blx _a2
+#    bl  _t1
+#    nop
+#    bl  _t1
+#    nop
+#    blx _t2
+#    nop
+#    blx  _t2
+#    bx   lr
+#    
+#  .globl _t2
+#  .thumb_func	_t2
+#_t2:
+#    bx   lr
+#    
+#    .data
+#_d1:  .long _t2
+#      .long _a1
+
+      
+      
+# Input file two:
+#
+#	.align	2
+#	.code	32
+#  .globl _a1
+#_a1:
+#    bl  _a1
+#    blx _a2
+#    bl  _t1
+#    blx _t2
+#    bx   lr
+#    
+#  .globl _a2
+#_a2:
+#    bx   lr
+#    
+#    .data
+#_d2:  .long _t1
+#      .long _a1
+
+
+
+      
\ No newline at end of file

Added: lld/trunk/test/mach-o/hello-world-armv7.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/hello-world-armv7.yaml?rev=214140&view=auto
==============================================================================
--- lld/trunk/test/mach-o/hello-world-armv7.yaml (added)
+++ lld/trunk/test/mach-o/hello-world-armv7.yaml Mon Jul 28 18:06:09 2014
@@ -0,0 +1,103 @@
+# RUN: lld -flavor darwin -arch armv7 -ios_version_min 7.0 %s -o %t  && \
+# RUN: llvm-nm %t | FileCheck %s
+#
+# Test that armv7 (thumb) hello-world can be linked into a mach-o executable
+#
+
+--- !mach-o
+arch:            armv7
+file-type:       MH_OBJECT
+flags:           [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID:        false
+OS:              unknown
+sections:        
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    alignment:       2
+    address:         0x0000000000000000
+    content:         [ 0x80, 0xB5, 0x40, 0xF2, 0x06, 0x00, 0x6F, 0x46, 
+                       0xC0, 0xF2, 0x00, 0x00, 0x78, 0x44, 0xFF, 0xF7, 
+                       0xF8, 0xEF, 0x00, 0x20, 0x80, 0xBD ]
+    relocations:     
+      - offset:          0x0000000E
+        type:            ARM_THUMB_RELOC_BR22
+        length:          2
+        pc-rel:          true
+        extern:          true
+        symbol:          1
+      - offset:          0x00000008
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          3
+        pc-rel:          false
+        value:           0x00000016
+      - offset:          0x00000006
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          3
+        pc-rel:          false
+        value:           0x0000000C
+      - offset:          0x00000002
+        scattered:       true
+        type:            ARM_RELOC_HALF_SECTDIFF
+        length:          2
+        pc-rel:          false
+        value:           0x00000016
+      - offset:          0x00000000
+        scattered:       true
+        type:            ARM_RELOC_PAIR
+        length:          2
+        pc-rel:          false
+        value:           0x0000000C
+  - segment:         __TEXT
+    section:         __cstring
+    type:            S_CSTRING_LITERALS
+    attributes:      [  ]
+    address:         0x0000000000000016
+    content:         [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
+global-symbols:  
+  - name:            _main
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    desc:            [ N_ARM_THUMB_DEF ]
+    value:           0x0000000000000000
+undefined-symbols: 
+  - name:            _printf
+    type:            N_UNDF
+    scope:           [ N_EXT ]
+    value:           0x0000000000000000
+...
+
+--- !mach-o
+arch:            armv7
+file-type:       MH_DYLIB
+flags:           [ ]
+install-name:    /usr/lib/libSystem.B.dylib
+sections:
+  - segment:         __TEXT
+    section:         __text
+    type:            S_REGULAR
+    attributes:      [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+    address:         0x0000000000000000
+    content:         [ 0x55 ]
+
+global-symbols:
+  - name:            _printf
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000001
+  - name:            dyld_stub_binder
+    type:            N_SECT
+    scope:           [ N_EXT ]
+    sect:            1
+    value:           0x0000000000000001
+
+...
+
+# CHECK:	{{[0-9a-f]+}} T _main
+# CHECK:	U _printf
+# CHECK:	U dyld_stub_binder





More information about the llvm-commits mailing list