COFF: ARM: Implement MOV32T relocation.
llvm-svn: 243201
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index b7d0dd1..55a3646 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -48,6 +48,7 @@
static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
+static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S,
uint64_t P) {
@@ -82,6 +83,26 @@
}
}
+static void applyMOV32T(uint8_t *Off, uint32_t V) {
+ uint16_t X = V;
+ or16(Off, ((X & 0x800) >> 1) | ((X >> 12) & 0xf));
+ or16(Off + 2, ((X & 0x700) << 4) | (X & 0xff));
+ X = V >> 16;
+ or16(Off + 4, ((X & 0x800) >> 1) | ((X >> 12) & 0xf));
+ or16(Off + 6, ((X & 0x700) << 4) | (X & 0xff));
+}
+
+void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, uint64_t S,
+ uint64_t P) {
+ switch (Type) {
+ case IMAGE_REL_ARM_ADDR32: add32(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_ARM_ADDR32NB: add32(Off, S); break;
+ case IMAGE_REL_ARM_MOV32T: applyMOV32T(Off, S + Config->ImageBase); break;
+ default:
+ llvm::report_fatal_error("Unsupported relocation type");
+ }
+}
+
void SectionChunk::writeTo(uint8_t *Buf) {
if (!hasData())
return;
@@ -102,6 +123,9 @@
case IMAGE_FILE_MACHINE_I386:
applyRelX86(Off, Rel.Type, S, P);
break;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ applyRelARM(Off, Rel.Type, S, P);
+ break;
default:
llvm_unreachable("unknown machine type");
}
@@ -125,6 +149,12 @@
if (Rel.Type == IMAGE_REL_I386_DIR32)
return IMAGE_REL_BASED_HIGHLOW;
return IMAGE_REL_BASED_ABSOLUTE;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ if (Rel.Type == IMAGE_REL_ARM_ADDR32)
+ return IMAGE_REL_BASED_HIGHLOW;
+ if (Rel.Type == IMAGE_REL_ARM_MOV32T)
+ return IMAGE_REL_BASED_ARM_MOV32T;
+ return IMAGE_REL_BASED_ABSOLUTE;
default:
llvm_unreachable("unknown machine type");
}
diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
index e471699..dcb9bc0 100644
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -139,6 +139,7 @@
bool isCOMDAT() const;
void applyRelX64(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
void applyRelX86(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
+ void applyRelARM(uint8_t *Off, uint16_t Type, uint64_t S, uint64_t P);
// Called if the garbage collector decides to not include this chunk
// in a final output. It's supposed to print out a log message to stdout.
diff --git a/lld/test/COFF/armnt-mov32t-exec.test b/lld/test/COFF/armnt-mov32t-exec.test
new file mode 100644
index 0000000..8caf436
--- /dev/null
+++ b/lld/test/COFF/armnt-mov32t-exec.test
@@ -0,0 +1,58 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld -flavor link /base:0x400000 /out:%t.exe /subsystem:console /entry:get_function %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: 40 f2 00 00 movw r0, #0
+# BEFORE: 8: c0 f2 00 00 movt r0, #0
+# BEFORE: c: 70 47 bx lr
+
+# AFTER: Disassembly of section .text:
+# AFTER: 1000: 70 47 bx lr
+# AFTER: 1002: 00 bf nop
+# AFTER: 1004: 41 f2 01 00 movw r0, #4097
+# AFTER: 1008: c0 f2 40 00 movt r0, #64
+# AFTER: 100c: 70 47 bx lr
+
+---
+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: 704700BF40F20000C0F200007047
+ Relocations:
+ - VirtualAddress: 4
+ SymbolName: function
+ Type: 17
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: function
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: get_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/COFF/armnt-movt32t.test b/lld/test/COFF/armnt-movt32t.test
new file mode 100644
index 0000000..0bec67f
--- /dev/null
+++ b/lld/test/COFF/armnt-movt32t.test
@@ -0,0 +1,70 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld -flavor link2 /base:0x400000 /entry:get_buffer /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: 40 f2 00 00 movw r0, #0
+# BEFORE: 4: c0 f2 00 00 movt r0, #0
+# BEFORE: 8: 70 47 bx lr
+
+# AFTER: Disassembly of section .text:
+# AFTER: 0: 41 f2 00 00 movw r0, #4096
+# AFTER: 4: c0 f2 40 00 movt r0, #64
+# AFTER: 8: 70 47 bx lr
+
+---
+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: 40F20000C0F200007047
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: buffer
+ Type: 17
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: '62756666657200'
+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: .rdata
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 7
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: get_buffer
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: buffer
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+...