diff options
-rw-r--r-- | lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp | 9 | ||||
-rw-r--r-- | lld/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml | 55 | ||||
-rw-r--r-- | lld/test/pecoff/Inputs/armnt-addr32-exec.s | 24 | ||||
-rw-r--r-- | lld/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml | 39 | ||||
-rw-r--r-- | lld/test/pecoff/Inputs/armnt-mov32t-exec.s | 30 | ||||
-rw-r--r-- | lld/test/pecoff/armnt-addr32-exec.test | 11 | ||||
-rw-r--r-- | lld/test/pecoff/armnt-mov32t-exec.test | 19 |
7 files changed, 186 insertions, 1 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp index 5cd892f6121..9a15901e82c 100644 --- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp @@ -587,9 +587,14 @@ void AtomChunk::applyRelocationsARM(uint8_t *Buffer, if (R->kindNamespace() != Reference::KindNamespace::COFF) continue; + bool AssumeTHUMBCode = false; + if (auto Target = cast_or_null<DefinedAtom>(R->target())) + AssumeTHUMBCode = Target->permissions() == DefinedAtom::permR_X || + Target->permissions() == DefinedAtom::permRWX; + const auto AtomOffset = R->offsetInAtom(); const auto FileOffset = Layout->_fileOffset; - const auto TargetAddr = AtomRVA[R->target()]; + const auto TargetAddr = AtomRVA[R->target()] | (AssumeTHUMBCode ? 1 : 0); auto RelocSite16 = reinterpret_cast<ulittle16_t *>(Buffer + FileOffset + AtomOffset); auto RelocSite32 = @@ -605,10 +610,12 @@ void AtomChunk::applyRelocationsARM(uint8_t *Buffer, applyThumbMoveImmediate(&RelocSite16[2], (TargetAddr + ImageBase) >> 16); break; case llvm::COFF::IMAGE_REL_ARM_BRANCH24T: + // NOTE: the thumb bit will implicitly be truncated properly applyThumbBranchImmediate(RelocSite16, TargetAddr - AtomRVA[Atom] - AtomOffset - 4); break; case llvm::COFF::IMAGE_REL_ARM_BLX23T: + // NOTE: the thumb bit will implicitly be truncated properly applyThumbBranchImmediate(RelocSite16, TargetAddr - AtomRVA[Atom] - AtomOffset - 4); break; diff --git a/lld/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml b/lld/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml new file mode 100644 index 00000000000..b550f58c03e --- /dev/null +++ b/lld/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml @@ -0,0 +1,55 @@ +--- +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: '7047' + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '00000000' + Relocations: + - VirtualAddress: 0 + SymbolName: function + Type: 1 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 2 + NumberOfRelocations: 0 + 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: 4 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 2 + - Name: function + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: fps + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/pecoff/Inputs/armnt-addr32-exec.s b/lld/test/pecoff/Inputs/armnt-addr32-exec.s new file mode 100644 index 00000000000..6a0776de7dd --- /dev/null +++ b/lld/test/pecoff/Inputs/armnt-addr32-exec.s @@ -0,0 +1,24 @@ + +# __declspec(dllexport) void function(void) { } +# const void * const fps[] = { &function, }; + + .syntax unified + .thumb + .text + + .def function + .scl 2 + .type 32 + .endef + .global function + .align 2 + .thumb_func +function: + bx lr + + .section .rdata,"rd" + .global fps + .align 2 +fps: + .long function + diff --git a/lld/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml b/lld/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml new file mode 100644 index 00000000000..a4630bcb9e0 --- /dev/null +++ b/lld/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml @@ -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: 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/pecoff/Inputs/armnt-mov32t-exec.s b/lld/test/pecoff/Inputs/armnt-mov32t-exec.s new file mode 100644 index 00000000000..10a20f468c3 --- /dev/null +++ b/lld/test/pecoff/Inputs/armnt-mov32t-exec.s @@ -0,0 +1,30 @@ + +# void function(void) { } +# void *get_function() { return &function; } + + .syntax unified + .thumb + .text + + .def function + .scl 2 + .type 32 + .endef + .global function + .align 2 + .thumb_func +function: + bx lr + + .def get_function + .scl 2 + .type 32 + .endef + .global get_function + .align 2 + .thumb_func +get_function: + movw r0, :lower16:function + movt r0, :upper16:function + bx lr + diff --git a/lld/test/pecoff/armnt-addr32-exec.test b/lld/test/pecoff/armnt-addr32-exec.test new file mode 100644 index 00000000000..be223a0e7e5 --- /dev/null +++ b/lld/test/pecoff/armnt-addr32-exec.test @@ -0,0 +1,11 @@ +# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-addr32-exec.obj.yaml +# RUN: llvm-objdump -s %t.obj | FileCheck %s -check-prefix BEFORE +# RUN: lld -flavor link /out:%t.exe /entry:function /subsystem:console %t.obj +# RUN: llvm-objdump -s %t.exe | FileCheck %s -check-prefix AFTER + +BEFORE: Contents of section .rdata: +BEFORE: 0000 00000000 + +AFTER: Contents of section .rdata: +AFTER: 1000 01204000 + diff --git a/lld/test/pecoff/armnt-mov32t-exec.test b/lld/test/pecoff/armnt-mov32t-exec.test new file mode 100644 index 00000000000..c98c9cf10cd --- /dev/null +++ b/lld/test/pecoff/armnt-mov32t-exec.test @@ -0,0 +1,19 @@ +# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-mov32t-exec.obj.yaml +# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE +# RUN: lld -flavor link /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 + |