The previously existing patch needed some modifications to fit on top of lld 3.9. Patch 2 makes sure that one still can use the lld built in this way for linking in MSVC mode. Patch 3 fixes linking binaries larger than 4 MB or so (previously the binaries linked fine but didn't work). Patch 4 makes sure to error out if the relocations are too far away (instead of producing a broken binary), which happens after 16 MB. Patch 5 fixes relocations that have an offset, which probably happens in hand-written assembly (in libav).
78 lines
3.3 KiB
Diff
78 lines
3.3 KiB
Diff
From c3fa3c7975a537df2e668ea59f074ce5be95b4f5 Mon Sep 17 00:00:00 2001
|
|
From: Saleem Abdulrasool <compnerd@compnerd.org>
|
|
Date: Fri, 5 Aug 2016 18:20:31 +0000
|
|
Subject: [PATCH 5/5] COFF ARM: Apply an existing offset in MOV32T relocations
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Don't blindly OR in the new value, but clear the existing one, since it can be
|
|
nonzero. Read out the existing value before, and add into the desired offset.
|
|
(The add is done outside of the applyMOV, to handle potential overflow between
|
|
the two.)
|
|
|
|
Patch by Martin Storsjö!
|
|
|
|
Cherry-picked from SVN trunk commit 277846, git mirror commit
|
|
3d39965b0cdd0.
|
|
---
|
|
COFF/Chunks.cpp | 16 ++++++++++++++--
|
|
test/COFF/reloc-arm.test | 4 ++--
|
|
2 files changed, 16 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
|
|
index fb60a8b..b8d706e 100644
|
|
--- a/COFF/Chunks.cpp
|
|
+++ b/COFF/Chunks.cpp
|
|
@@ -81,11 +81,23 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
|
|
}
|
|
|
|
static void applyMOV(uint8_t *Off, uint16_t V) {
|
|
- or16(Off, ((V & 0x800) >> 1) | ((V >> 12) & 0xf));
|
|
- or16(Off + 2, ((V & 0x700) << 4) | (V & 0xff));
|
|
+ write16le(Off, (read16le(Off) & 0xfbf0) | ((V & 0x800) >> 1) | ((V >> 12) & 0xf));
|
|
+ write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff));
|
|
+}
|
|
+
|
|
+static uint16_t readMOV(uint8_t *Off) {
|
|
+ uint16_t Opcode1 = read16le(Off);
|
|
+ uint16_t Opcode2 = read16le(Off + 2);
|
|
+ uint16_t Imm = (Opcode2 & 0x00ff) | ((Opcode2 >> 4) & 0x0700);
|
|
+ Imm |= ((Opcode1 << 1) & 0x0800) | ((Opcode1 & 0x000f) << 12);
|
|
+ return Imm;
|
|
}
|
|
|
|
static void applyMOV32T(uint8_t *Off, uint32_t V) {
|
|
+ uint16_t ImmW = readMOV(Off); // read MOVW operand
|
|
+ uint16_t ImmT = readMOV(Off + 4); // read MOVT operand
|
|
+ uint32_t Imm = ImmW | (ImmT << 16);
|
|
+ V += Imm; // add the immediate offset
|
|
applyMOV(Off, V); // set MOVW operand
|
|
applyMOV(Off + 4, V >> 16); // set MOVT operand
|
|
}
|
|
diff --git a/test/COFF/reloc-arm.test b/test/COFF/reloc-arm.test
|
|
index f7656e7..b9699e8 100644
|
|
--- a/test/COFF/reloc-arm.test
|
|
+++ b/test/COFF/reloc-arm.test
|
|
@@ -5,7 +5,7 @@
|
|
# CHECK: .text:
|
|
# CHECK: 402000 01104000 00000000 00000000 00000000
|
|
# CHECK: 402010 01100000 00000000 00000000 00000000
|
|
-# CHECK: 402020 01000100 00004000 00000000 00000000
|
|
+# CHECK: 402020 41f20009 c0f24009 00000000 00000000
|
|
# CHECK: 402030 fe07e62f 00000000 00000000 00000000
|
|
# CHECK: 402040 3e04de2f 00000000 00000000 00000000
|
|
# CHECK: 402050 fe07d62f 00000000 00000000 00000000
|
|
@@ -23,7 +23,7 @@ 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: 4096
|
|
- SectionData: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f8000000000000000000000000
|
|
+ SectionData: 00000000000000000000000000000000000000000000000000000000000000004ff6ff79cff6ff79000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f8000000000000000000000000
|
|
Relocations:
|
|
- VirtualAddress: 0
|
|
SymbolName: foo
|
|
--
|
|
2.7.4
|
|
|