summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2015-01-08 04:19:08 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2015-01-08 04:19:08 +0000
commitb9c402ed25238f9fd4b61180b2e0c4105d867590 (patch)
treea84d3910132ac4320b77a566d1740fd87a6ca71f
parent341f0e6ee0cb472cb23baacbfd4f30be0e769037 (diff)
downloadbcm5719-llvm-b9c402ed25238f9fd4b61180b2e0c4105d867590.tar.gz
bcm5719-llvm-b9c402ed25238f9fd4b61180b2e0c4105d867590.zip
PE/COFF: add support to import functions in ARM NT
This is necessary to support linking a basic program which references symbols outside of the module itself. Add the import thunk for ARM NT style imports. This allows us to create the reference. However, it is still insufficient to generate executables that will run due to base relocations not being emitted for the import. llvm-svn: 225428
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp53
-rw-r--r--lld/test/pecoff/Inputs/armnt-import.obj.yaml39
-rw-r--r--lld/test/pecoff/Inputs/armnt-import.s21
-rwxr-xr-xlld/test/pecoff/Inputs/library.libbin0 -> 1694 bytes
-rw-r--r--lld/test/pecoff/armnt-imports.test11
5 files changed, 117 insertions, 7 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
index 6c80a146c77..dc158cd4f93 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
@@ -154,10 +154,18 @@ const uint8_t FuncAtomContentX86[] = {
0xcc, 0xcc // INT 3; INT 3
};
+const uint8_t FuncAtomContentARMNT[] = {
+ 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0
+ 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0
+ 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
+};
+
static void setJumpInstTarget(COFFLinkerInternalAtom *src, const Atom *dst,
int off, MachineTypes machine) {
COFFReference *ref;
+
switch (machine) {
+ default: llvm::report_fatal_error("unsupported machine type");
case llvm::COFF::IMAGE_FILE_MACHINE_I386:
ref = new COFFReference(dst, off, llvm::COFF::IMAGE_REL_I386_DIR32,
Reference::KindArch::x86);
@@ -166,9 +174,12 @@ static void setJumpInstTarget(COFFLinkerInternalAtom *src, const Atom *dst,
ref = new COFFReference(dst, off, llvm::COFF::IMAGE_REL_AMD64_REL32,
Reference::KindArch::x86_64);
break;
- default:
- llvm::report_fatal_error("unsupported machine type");
+ case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
+ ref = new COFFReference(dst, off, llvm::COFF::IMAGE_REL_ARM_MOV32T,
+ Reference::KindArch::ARM);
+ break;
}
+
src->addReference(std::unique_ptr<COFFReference>(ref));
}
@@ -177,9 +188,22 @@ class FuncAtom : public COFFLinkerInternalAtom {
public:
FuncAtom(const File &file, StringRef symbolName,
const COFFSharedLibraryAtom *impAtom, MachineTypes machine)
- : COFFLinkerInternalAtom(file, /*oridnal*/ 0, createContent(),
+ : COFFLinkerInternalAtom(file, /*oridnal*/ 0, createContent(machine),
symbolName) {
- setJumpInstTarget(this, impAtom, 2, machine);
+ size_t Offset;
+
+ switch (machine) {
+ default: llvm::report_fatal_error("unsupported machine type");
+ case llvm::COFF::IMAGE_FILE_MACHINE_I386:
+ case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
+ Offset = 2;
+ break;
+ case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
+ Offset = 0;
+ break;
+ }
+
+ setJumpInstTarget(this, impAtom, Offset, machine);
}
uint64_t ordinal() const override { return 0; }
@@ -189,9 +213,24 @@ public:
ContentPermissions permissions() const override { return permR_X; }
private:
- std::vector<uint8_t> createContent() const {
- return std::vector<uint8_t>(
- FuncAtomContentX86, FuncAtomContentX86 + sizeof(FuncAtomContentX86));
+ std::vector<uint8_t> createContent(MachineTypes machine) const {
+ const uint8_t *Data;
+ size_t Size;
+
+ switch (machine) {
+ default: llvm::report_fatal_error("unsupported machine type");
+ case llvm::COFF::IMAGE_FILE_MACHINE_I386:
+ case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
+ Data = FuncAtomContentX86;
+ Size = sizeof(FuncAtomContentX86);
+ break;
+ case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
+ Data = FuncAtomContentARMNT;
+ Size = sizeof(FuncAtomContentARMNT);
+ break;
+ }
+
+ return std::vector<uint8_t>(Data, Data + Size);
}
};
diff --git a/lld/test/pecoff/Inputs/armnt-import.obj.yaml b/lld/test/pecoff/Inputs/armnt-import.obj.yaml
new file mode 100644
index 00000000000..08876eeb0d4
--- /dev/null
+++ b/lld/test/pecoff/Inputs/armnt-import.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: 40F20000C0F2000000680047
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: __imp_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: 12
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __imp_function
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/pecoff/Inputs/armnt-import.s b/lld/test/pecoff/Inputs/armnt-import.s
new file mode 100644
index 00000000000..2790d0edc8d
--- /dev/null
+++ b/lld/test/pecoff/Inputs/armnt-import.s
@@ -0,0 +1,21 @@
+
+# void __declspec(dllimport) function(void);
+# int mainCRTStartup(void) { return function(); }
+
+ .syntax unified
+ .thumb
+ .text
+
+ .def mainCRTStartup
+ .scl 2
+ .type 32
+ .endef
+ .global mainCRTStartup
+ .align 2
+ .thumb_func
+mainCRTStartup:
+ movw r0, :lower16:__imp_function
+ movt r0, :upper16:__imp_function
+ ldr r0, [r0]
+ bx r0
+
diff --git a/lld/test/pecoff/Inputs/library.lib b/lld/test/pecoff/Inputs/library.lib
new file mode 100755
index 00000000000..2f4207d7983
--- /dev/null
+++ b/lld/test/pecoff/Inputs/library.lib
Binary files differ
diff --git a/lld/test/pecoff/armnt-imports.test b/lld/test/pecoff/armnt-imports.test
new file mode 100644
index 00000000000..596270909c5
--- /dev/null
+++ b/lld/test/pecoff/armnt-imports.test
@@ -0,0 +1,11 @@
+# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-import.obj.yaml
+# RUN: lld -flavor link /out:%t.exe /subsystem:console %t.obj %p/Inputs/library.lib
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s
+
+CHECK: Import {
+CHECK: Name: library.dll
+CHECK: ImportLookupTableRVA: 0x4000
+CHECK: ImportAddressTableRVA: 0x2000
+CHECK: Symbol: function (0)
+CHECK: }
+
OpenPOWER on IntegriCloud