summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-07-29 19:25:00 +0000
committerRui Ueyama <ruiu@google.com>2015-07-29 19:25:00 +0000
commit8bc43a142ba4c852820ec1e285f6ead6229baa7c (patch)
tree9add0eed393ef2c966e1c08c684a737423a0c88f
parent56965f4b32f6ac6234fdc59cd932d471451c0eee (diff)
downloadbcm5719-llvm-8bc43a142ba4c852820ec1e285f6ead6229baa7c.tar.gz
bcm5719-llvm-8bc43a142ba4c852820ec1e285f6ead6229baa7c.zip
COFF: ARM: Fix relocations to thumb code.
Windows ARM is the thumb ARM environment, and pointers to thumb code needs to have its LSB set. When we apply relocations, we need to adjust the LSB if it points to an executable section. llvm-svn: 243560
-rw-r--r--lld/COFF/Chunks.cpp3
-rw-r--r--lld/COFF/Symbols.h4
-rw-r--r--lld/COFF/Writer.cpp7
-rw-r--r--lld/test/COFF/armnt-mov32t-exec.test2
4 files changed, 15 insertions, 1 deletions
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
index a68e258efc4..4e41f2fcea9 100644
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -105,6 +105,9 @@ static void applyBranchImm(uint8_t *Off, int32_t V) {
void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
uint64_t P) {
uint64_t S = Sym->getRVA();
+ // Pointer to thumb code must have the LSB set.
+ if (Sym->isExecutable())
+ S |= 1;
switch (Type) {
case IMAGE_REL_ARM_ADDR32: add32(Off, S + Config->ImageBase); break;
case IMAGE_REL_ARM_ADDR32NB: add32(Off, S); break;
diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h
index eae1bfa203e..eb9afd38008 100644
--- a/lld/COFF/Symbols.h
+++ b/lld/COFF/Symbols.h
@@ -138,6 +138,10 @@ public:
// Returns the output section index.
// Used to implement SECTION relocation type.
uint64_t getSectionIndex();
+
+ // Returns true if this symbol points to an executable (e.g. .text) section.
+ // Used to implement ARM relocations.
+ bool isExecutable();
};
// Symbols defined via a COFF object file.
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 62ac95cc95a..4a9c5f896af 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -690,5 +690,12 @@ uint64_t Defined::getSectionIndex() {
llvm::report_fatal_error("SECTION relocation points to a non-regular symbol");
}
+bool Defined::isExecutable() {
+ const auto X = IMAGE_SCN_MEM_EXECUTE;
+ if (auto *D = dyn_cast<DefinedRegular>(this))
+ return D->getChunk()->getOutputSection()->getPermissions() & X;
+ return isa<DefinedImportThunk>(this);
+}
+
} // namespace coff
} // namespace lld
diff --git a/lld/test/COFF/armnt-mov32t-exec.test b/lld/test/COFF/armnt-mov32t-exec.test
index 847c7b92a62..91b814caa5e 100644
--- a/lld/test/COFF/armnt-mov32t-exec.test
+++ b/lld/test/COFF/armnt-mov32t-exec.test
@@ -2,7 +2,7 @@
# RUN: yaml2obj < %s > %t.obj
# 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: lld -flavor link2 /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:
OpenPOWER on IntegriCloud