ReaderWriter: teach the writer about IMAGE_REL_ARM_BRANCH24T
authorSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 2 Jan 2015 18:51:59 +0000 (18:51 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Fri, 2 Jan 2015 18:51:59 +0000 (18:51 +0000)
This adds support for IMAGE_REL_ARM_BRANCH24T relocations.  Similar to the
IMAGE_REL_ARM_BLX32T relocation, this relocation requires munging an
instruction.  The instruction encoding is quite similar, allowing us to reuse
the same munging implementation.  This is needed by the entry point stubs for
modules provided by MSVCRT.

llvm-svn: 225082

lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
lld/test/pecoff/Inputs/armnt-branch24t.obj.yaml [new file with mode: 0644]
lld/test/pecoff/Inputs/armnt-branch24t.s [new file with mode: 0644]
lld/test/pecoff/armnt-branch24t.test [new file with mode: 0644]

index ec8a83b..5cd892f 100644 (file)
@@ -561,10 +561,12 @@ static void applyThumbMoveImmediate(ulittle16_t *mov, uint16_t imm) {
 static void applyThumbBranchImmediate(ulittle16_t *bl, int32_t imm) {
   // BL(T1):  |11110|S|imm10|11|J1|1|J2|imm11|
   //          imm32 = sext S:I1:I2:imm10:imm11:'0'
+  // B.W(T4): |11110|S|imm10|10|J1|1|J2|imm11|
+  //          imm32 = sext S:I1:I2:imm10:imm11:'0'
   //
   //          I1 = ~(J1 ^ S), I2 = ~(J2 ^ S)
 
-  assert((~abs(imm) & (-1 << 24)) && "bl out of range");
+  assert((~abs(imm) & (-1 << 24)) && "bl/b.w out of range");
 
   uint32_t S = (imm < 0 ? 1 : 0);
   uint32_t J1 = ((~imm & 0x00800000) >> 23) ^ S;
@@ -602,6 +604,10 @@ void AtomChunk::applyRelocationsARM(uint8_t *Buffer,
         applyThumbMoveImmediate(&RelocSite16[0], (TargetAddr + ImageBase) >>  0);
         applyThumbMoveImmediate(&RelocSite16[2], (TargetAddr + ImageBase) >> 16);
         break;
+      case llvm::COFF::IMAGE_REL_ARM_BRANCH24T:
+        applyThumbBranchImmediate(RelocSite16,
+                                  TargetAddr - AtomRVA[Atom] - AtomOffset - 4);
+        break;
       case llvm::COFF::IMAGE_REL_ARM_BLX23T:
         applyThumbBranchImmediate(RelocSite16,
                                   TargetAddr - AtomRVA[Atom] - AtomOffset - 4);
diff --git a/lld/test/pecoff/Inputs/armnt-branch24t.obj.yaml b/lld/test/pecoff/Inputs/armnt-branch24t.obj.yaml
new file mode 100644 (file)
index 0000000..02815a4
--- /dev/null
@@ -0,0 +1,39 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_ARMNT
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     704700BF202000F000B8
+    Relocations:
+      - VirtualAddress:  6
+        SymbolName:      identity
+        Type:            20
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition: 
+      Length:          10
+      NumberOfRelocations: 1
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          1
+  - Name:            identity
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            function
+    Value:           4
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/pecoff/Inputs/armnt-branch24t.s b/lld/test/pecoff/Inputs/armnt-branch24t.s
new file mode 100644 (file)
index 0000000..5fcd1a4
--- /dev/null
@@ -0,0 +1,27 @@
+
+@ int ___declspec(noinline) identity(int i) { return i; }
+@ int function(void) { return identity(32); }
+
+       .syntax unified
+       .thumb
+       .text
+
+       .def identity
+               .scl 2
+               .type 32
+       .endef
+       .global identity
+       .align 2
+       .code16
+       .thumb_func
+identity:
+       bx lr
+
+       .def function
+               .scl 2
+               .type 32
+       .endef
+function:
+       movs r0, #32
+       b identity
+
diff --git a/lld/test/pecoff/armnt-branch24t.test b/lld/test/pecoff/armnt-branch24t.test
new file mode 100644 (file)
index 0000000..bcb0a51
--- /dev/null
@@ -0,0 +1,18 @@
+# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-branch24t.obj.yaml
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld -flavor link /entry:function /subsystem:console /out:%t.exe %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
+
+BEFORE: Disassembly of section .text:
+BEFORE:        0: 70 47         bx lr
+BEFORE:        2: 00 bf         nop
+BEFORE:        4: 20 20         movs r0, #32
+BEFORE:        6: 00 f0 00 b8   b.w #0
+
+AFTER: Disassembly of section .text:
+AFTER: .text:
+AFTER:     1000: 70 47         bx lr
+AFTER:     1002: 00 bf         nop
+AFTER:     1004: 20 20         movs r0, #32
+AFTER:     1006: ff f7 fb bf   b.w #-10
+