Update patches for lld 3.9
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).
This commit is contained in:
1 parent
3eb63bea3d
commit
93a77a441a
5 files changed
+341
-65
No files matched your search
+57
-65
@@ -1,29 +1,35 @@
|
||||
From 38ed8e461edd6df0c7f2ba2d0e8d36f6288d231e Mon Sep 17 00:00:00 2001
|
||||
From 808dcadd650fd54174a0c033547a6668bf77e4f1 Mon Sep 17 00:00:00 2001
|
||||
From: Martell Malone <martellmalone@gmail.com>
|
||||
Date: Wed, 28 Oct 2015 19:32:16 +0000
|
||||
Subject: [PATCH] add support for gnu arguments in lld coff
|
||||
Subject: [PATCH 1/5] add support for gnu arguments in lld coff
|
||||
|
||||
---
|
||||
COFF/Driver.cpp | 31 ++++++++++++++++++++++++++++++-
|
||||
COFF/Driver.h | 3 +++
|
||||
COFF/DriverUtils.cpp | 2 +-
|
||||
COFF/Options.td | 20 ++++++++++++++++++++
|
||||
tools/lld/lld.cpp | 21 +++++++++++++++++++++
|
||||
5 files changed, 75 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
|
||||
index f528daf..34f422c 100644
|
||||
index bb6a60e..0821591 100644
|
||||
--- a/COFF/Driver.cpp
|
||||
+++ b/COFF/Driver.cpp
|
||||
@@ -119,6 +119,7 @@ void LinkerDriver::parseDirectives(StringRef S) {
|
||||
case OPT_editandcontinue:
|
||||
@@ -125,6 +125,7 @@ void LinkerDriver::parseDirectives(StringRef S) {
|
||||
case OPT_fastfail:
|
||||
case OPT_guardsym:
|
||||
case OPT_throwingnew:
|
||||
+ case OPT_aligncomm:
|
||||
break;
|
||||
default:
|
||||
error(Twine(Arg->getSpelling()) + " is not allowed in .drectve");
|
||||
@@ -147,6 +148,31 @@ StringRef LinkerDriver::doFindFile(StringRef Filename) {
|
||||
fatal(Arg->getSpelling() + " is not allowed in .drectve");
|
||||
@@ -153,6 +154,31 @@ StringRef LinkerDriver::doFindFile(StringRef Filename) {
|
||||
return Filename;
|
||||
}
|
||||
|
||||
+// Searches a given library from input search paths, which are filled
|
||||
+// from -L command line switches. Returns a path to an existent library file.
|
||||
+StringRef LinkerDriver::searchLibrary(StringRef Filename) {
|
||||
+// error("Unable to find library -l" + Filename);
|
||||
+
|
||||
+ std::vector<std::string> Names;
|
||||
+ if (Filename[0] == ':') {
|
||||
@@ -42,13 +48,14 @@ index f528daf..34f422c 100644
|
||||
+ return Alloc.save(Path.str());
|
||||
+ }
|
||||
+ }
|
||||
+ error("Unable to find library -l" + Filename);
|
||||
+ fatal("Unable to find library -l" + Filename);
|
||||
+ return "";
|
||||
+}
|
||||
+
|
||||
// Resolves a file path. This never returns the same path
|
||||
// (in that case, it returns None).
|
||||
Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
|
||||
@@ -438,6 +464,9 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
@@ -452,6 +478,9 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
// for /defaultlib option.
|
||||
std::vector<StringRef> Paths;
|
||||
std::vector<MemoryBufferRef> MBs;
|
||||
@@ -58,7 +65,7 @@ index f528daf..34f422c 100644
|
||||
for (auto *Arg : Args.filtered(OPT_INPUT))
|
||||
if (Optional<StringRef> Path = findFile(Arg->getValue()))
|
||||
Paths.push_back(*Path);
|
||||
@@ -559,7 +588,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
@@ -573,7 +602,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
if (Config->ImageBase == uint64_t(-1))
|
||||
Config->ImageBase = getDefaultImageBase();
|
||||
|
||||
@@ -68,10 +75,10 @@ index f528daf..34f422c 100644
|
||||
Config->SEHTable = Symtab.addRelative("___safe_se_handler_table", 0);
|
||||
Config->SEHCount = Symtab.addAbsolute("___safe_se_handler_count", 0);
|
||||
diff --git a/COFF/Driver.h b/COFF/Driver.h
|
||||
index e50da20..c716678 100644
|
||||
index 23969ee..230ec35 100644
|
||||
--- a/COFF/Driver.h
|
||||
+++ b/COFF/Driver.h
|
||||
@@ -87,6 +87,9 @@ private:
|
||||
@@ -84,6 +84,9 @@ private:
|
||||
StringRef doFindFile(StringRef Filename);
|
||||
StringRef doFindLib(StringRef Filename);
|
||||
|
||||
@@ -82,10 +89,10 @@ index e50da20..c716678 100644
|
||||
void addLibSearchPaths();
|
||||
|
||||
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
|
||||
index 391a8ab..e876de3 100644
|
||||
index 5d7dc2b..e2f1f2d 100644
|
||||
--- a/COFF/DriverUtils.cpp
|
||||
+++ b/COFF/DriverUtils.cpp
|
||||
@@ -650,7 +650,7 @@ static const llvm::opt::OptTable::Info infoTable[] = {
|
||||
@@ -591,7 +591,7 @@ static const llvm::opt::OptTable::Info infoTable[] = {
|
||||
|
||||
class COFFOptTable : public llvm::opt::OptTable {
|
||||
public:
|
||||
@@ -95,10 +102,10 @@ index 391a8ab..e876de3 100644
|
||||
|
||||
// Parses a given list of options.
|
||||
diff --git a/COFF/Options.td b/COFF/Options.td
|
||||
index a21b8de..3418de5 100644
|
||||
index e5c9c5b..322b162 100644
|
||||
--- a/COFF/Options.td
|
||||
+++ b/COFF/Options.td
|
||||
@@ -92,6 +92,26 @@ def nosymtab : F<"nosymtab">;
|
||||
@@ -93,6 +93,26 @@ def nosymtab : F<"nosymtab">;
|
||||
// Flags for debugging
|
||||
def lldmap : Joined<["/", "-"], "lldmap:">;
|
||||
|
||||
@@ -125,60 +132,45 @@ index a21b8de..3418de5 100644
|
||||
//==============================================================================
|
||||
// The flags below do nothing. They are defined only for link.exe compatibility.
|
||||
//==============================================================================
|
||||
diff --git a/lib/Driver/UniversalDriver.cpp b/lib/Driver/UniversalDriver.cpp
|
||||
index 3dea7eb..268dafb 100644
|
||||
--- a/lib/Driver/UniversalDriver.cpp
|
||||
+++ b/lib/Driver/UniversalDriver.cpp
|
||||
@@ -95,6 +95,21 @@ static Flavor strToFlavor(StringRef str) {
|
||||
.Default(Flavor::invalid);
|
||||
diff --git a/tools/lld/lld.cpp b/tools/lld/lld.cpp
|
||||
index 8805e02..68c8735 100644
|
||||
--- a/tools/lld/lld.cpp
|
||||
+++ b/tools/lld/lld.cpp
|
||||
@@ -51,6 +51,24 @@ static Flavor getFlavor(StringRef S) {
|
||||
.Default(Invalid);
|
||||
}
|
||||
|
||||
+//std::pair<llvm::Triple::ObjectFileFormat, IMAGE_FILE_MACHINE_TYPE> getTargetFromEmulation
|
||||
+
|
||||
+static bool isPETarget(const llvm::opt::InputArgList &parsedArgs) {
|
||||
+ llvm::opt::Arg *argMachine = parsedArgs.getLastArg(OPT_m);
|
||||
+ if (!argMachine)
|
||||
+ return false;
|
||||
+ if (argMachine->containsValue("i386pe"))
|
||||
+ return true;
|
||||
+ if (argMachine->containsValue("i386pep"))
|
||||
+ return true;
|
||||
+ if (argMachine->containsValue("thumb2pe"))
|
||||
+ return true;
|
||||
+static bool isPETarget(const std::vector<const char *> &V) {
|
||||
+ for (auto It = V.begin(); It != V.end(); It++) {
|
||||
+ if (*It == StringRef("-m")) {
|
||||
+ It++;
|
||||
+ if (It == V.end())
|
||||
+ return false;
|
||||
+ if (*It == StringRef("i386pe"))
|
||||
+ return true;
|
||||
+ if (*It == StringRef("i386pep"))
|
||||
+ return true;
|
||||
+ if (*It == StringRef("thumb2pe"))
|
||||
+ return true;
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static ProgramNameParts parseProgramName(StringRef programName) {
|
||||
SmallVector<StringRef, 3> components;
|
||||
llvm::SplitString(programName, components, "-");
|
||||
@@ -198,6 +213,12 @@ bool UniversalDriver::link(llvm::MutableArrayRef<const char *> args,
|
||||
return true;
|
||||
}
|
||||
static Flavor parseProgname(StringRef Progname) {
|
||||
#if __APPLE__
|
||||
// Use Darwin driver for "ld" on Darwin.
|
||||
@@ -101,6 +119,9 @@ int main(int Argc, const char **Argv) {
|
||||
llvm_shutdown_obj Shutdown;
|
||||
|
||||
+ //Override gnu for pe targets to use coff
|
||||
+ if(isPETarget(parsedArgs)) {
|
||||
+ coff::link(args);
|
||||
+ return true;
|
||||
+ }
|
||||
std::vector<const char *> Args(Argv, Argv + Argc);
|
||||
+ if (isPETarget(Args))
|
||||
+ return !coff::link(Args);
|
||||
+
|
||||
Flavor flavor = getFlavor(args, parsedArgs);
|
||||
|
||||
// Switch to appropriate driver.
|
||||
diff --git a/lib/Driver/UniversalDriverOptions.td b/lib/Driver/UniversalDriverOptions.td
|
||||
index 14abc9c..38e620b 100644
|
||||
--- a/lib/Driver/UniversalDriverOptions.td
|
||||
+++ b/lib/Driver/UniversalDriverOptions.td
|
||||
@@ -11,6 +11,10 @@ def core : Flag<["-"], "core">,
|
||||
def target: Separate<["-"], "target">,
|
||||
HelpText<"Select the target">;
|
||||
|
||||
+// Used to override gnu pe targets
|
||||
+def m : Separate<["-"], "m">, MetaVarName<"<emulation>">,
|
||||
+ HelpText<"Select target emulation">;
|
||||
+
|
||||
def version: Flag<["-"], "version">,
|
||||
HelpText<"Display the version">;
|
||||
|
||||
switch (parseFlavor(Args)) {
|
||||
case Gnu:
|
||||
return !elf::link(Args);
|
||||
--
|
||||
2.6.3
|
||||
2.7.4
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
From f8cba388440ff846c5f479889fc64a03066ff39c Mon Sep 17 00:00:00 2001
|
||||
From: Martin Storsjo <martin@martin.st>
|
||||
Date: Mon, 8 Aug 2016 15:37:59 +0300
|
||||
Subject: [PATCH 2/5] Make the "gnu arguments in lld coff" patch not break
|
||||
using lld-link in normal MSVC mode
|
||||
|
||||
---
|
||||
COFF/Driver.cpp | 1 +
|
||||
COFF/DriverUtils.cpp | 5 ++++-
|
||||
COFF/Options.td | 2 ++
|
||||
3 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
|
||||
index 0821591..65cfa9f 100644
|
||||
--- a/COFF/Driver.cpp
|
||||
+++ b/COFF/Driver.cpp
|
||||
@@ -602,6 +602,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
||||
if (Config->ImageBase == uint64_t(-1))
|
||||
Config->ImageBase = getDefaultImageBase();
|
||||
|
||||
+ Symtab.addRelative(mangle("__ImageBase"), 0);
|
||||
Symtab.addRelative(mangle("__image_base__"), 0);
|
||||
if (Config->Machine == I386) {
|
||||
Config->SEHTable = Symtab.addRelative("___safe_se_handler_table", 0);
|
||||
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
|
||||
index e2f1f2d..f9c37ec 100644
|
||||
--- a/COFF/DriverUtils.cpp
|
||||
+++ b/COFF/DriverUtils.cpp
|
||||
@@ -591,7 +591,10 @@ static const llvm::opt::OptTable::Info infoTable[] = {
|
||||
|
||||
class COFFOptTable : public llvm::opt::OptTable {
|
||||
public:
|
||||
- COFFOptTable() : OptTable(infoTable) {}
|
||||
+ // GNU ld option style support requires case sensitive option matching
|
||||
+ // (for -L vs -l), needing aliases for a few link.exe options that can
|
||||
+ // appear in upper case in embedded directives in libraries.
|
||||
+ COFFOptTable() : OptTable(infoTable, false) {}
|
||||
};
|
||||
|
||||
// Parses a given list of options.
|
||||
diff --git a/COFF/Options.td b/COFF/Options.td
|
||||
index 322b162..4e7338a 100644
|
||||
--- a/COFF/Options.td
|
||||
+++ b/COFF/Options.td
|
||||
@@ -19,11 +19,13 @@ def align : P<"align", "Section alignment">;
|
||||
def alternatename : P<"alternatename", "Define weak alias">;
|
||||
def base : P<"base", "Base address of the program">;
|
||||
def defaultlib : P<"defaultlib", "Add the library to the list of input files">;
|
||||
+def DEFAULTLIB : P<"DEFAULTLIB", "">, Alias<defaultlib>;
|
||||
def delayload : P<"delayload", "Delay loaded DLL name">;
|
||||
def entry : P<"entry", "Name of entry point symbol">;
|
||||
def export : P<"export", "Export a function">;
|
||||
// No help text because /failifmismatch is not intended to be used by the user.
|
||||
def failifmismatch : P<"failifmismatch", "">;
|
||||
+def FAILIFMISMATCH : P<"FAILIFMISMATCH", "">, Alias<failifmismatch>;
|
||||
def heap : P<"heap", "Size of the heap">;
|
||||
def implib : P<"implib", "Import library name">;
|
||||
def libpath : P<"libpath", "Additional library search path">;
|
||||
--
|
||||
2.7.4
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
From 2f3ad0343836886143c1f8ac83552c6734e05205 Mon Sep 17 00:00:00 2001
|
||||
From: Saleem Abdulrasool <compnerd@compnerd.org>
|
||||
Date: Fri, 5 Aug 2016 17:28:21 +0000
|
||||
Subject: [PATCH 3/5] COFF ARM: Clear the J1 and J2 bits when applying
|
||||
relocations to 24 bit branches
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The opcode for the bl branches can initially be F000 F800, i.e.
|
||||
the J1 and J2 bits are already set. Therefore mask these bits out
|
||||
before or'ing in the new bits.
|
||||
|
||||
Patch by Martin Storsjö!
|
||||
|
||||
Cherry-picked from SVN trunk commit 277836, git mirror commit
|
||||
7b7d94e63a.
|
||||
---
|
||||
COFF/Chunks.cpp | 3 ++-
|
||||
test/COFF/reloc-arm.test | 13 +++++++++++--
|
||||
2 files changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
|
||||
index 1c1b181..2e6f535 100644
|
||||
--- a/COFF/Chunks.cpp
|
||||
+++ b/COFF/Chunks.cpp
|
||||
@@ -103,7 +103,8 @@ static void applyBranch24T(uint8_t *Off, int32_t V) {
|
||||
uint32_t J1 = ((~V >> 23) & 1) ^ S;
|
||||
uint32_t J2 = ((~V >> 22) & 1) ^ S;
|
||||
or16(Off, (S << 10) | ((V >> 12) & 0x3ff));
|
||||
- or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
|
||||
+ // Clear out the J1 and J2 bits which may be set.
|
||||
+ write16le(Off + 2, (read16le(Off + 2) & 0xd000) | (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
|
||||
}
|
||||
|
||||
void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
|
||||
diff --git a/test/COFF/reloc-arm.test b/test/COFF/reloc-arm.test
|
||||
index 11b863d..f7656e7 100644
|
||||
--- a/test/COFF/reloc-arm.test
|
||||
+++ b/test/COFF/reloc-arm.test
|
||||
@@ -9,7 +9,7 @@
|
||||
# CHECK: 402030 fe07e62f 00000000 00000000 00000000
|
||||
# CHECK: 402040 3e04de2f 00000000 00000000 00000000
|
||||
# CHECK: 402050 fe07d62f 00000000 00000000 00000000
|
||||
-# CHECK: 402060 00000000 00000000 00000000 00000000
|
||||
+# CHECK: 402060 fef0cef7 00000000 00000000 00000000
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
@@ -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: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
+ SectionData: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000f8000000000000000000000000
|
||||
Relocations:
|
||||
- VirtualAddress: 0
|
||||
SymbolName: foo
|
||||
@@ -43,6 +43,9 @@ sections:
|
||||
- VirtualAddress: 80
|
||||
SymbolName: foo
|
||||
Type: 21 # IMAGE_REL_AMD64_BLX23T
|
||||
+ - VirtualAddress: 96
|
||||
+ SymbolName: bar
|
||||
+ Type: 20 # IMAGE_REL_ARM_BRANCH24T
|
||||
symbols:
|
||||
- Name: .aaa
|
||||
Value: 0
|
||||
@@ -68,4 +71,10 @@ symbols:
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
+ - Name: bar
|
||||
+ Value: 0x500000
|
||||
+ SectionNumber: 1
|
||||
+ SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
+ ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
--
|
||||
2.7.4
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
From 13f5a9ac209dd87b8e3c22151a139954a49a0674 Mon Sep 17 00:00:00 2001
|
||||
From: Saleem Abdulrasool <compnerd@compnerd.org>
|
||||
Date: Fri, 5 Aug 2016 17:33:24 +0000
|
||||
Subject: [PATCH 4/5] COFF ARM: Error out if 24 bit thumb branches are out of
|
||||
range
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In the ELF linker, the same situation already errors out with "relocation
|
||||
R_ARM_THM_CALL out of range".
|
||||
|
||||
Patch by Martin Storsjö!
|
||||
|
||||
Cherry-picked from SVN trunk commit 277838, git mirror commit
|
||||
97497d40eee0.
|
||||
---
|
||||
COFF/Chunks.cpp | 2 ++
|
||||
test/COFF/Inputs/far-arm-thumb-abs.s | 2 ++
|
||||
test/COFF/arm-thumb-branch-error.s | 10 ++++++++++
|
||||
3 files changed, 14 insertions(+)
|
||||
create mode 100644 test/COFF/Inputs/far-arm-thumb-abs.s
|
||||
create mode 100644 test/COFF/arm-thumb-branch-error.s
|
||||
|
||||
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
|
||||
index 2e6f535..fb60a8b 100644
|
||||
--- a/COFF/Chunks.cpp
|
||||
+++ b/COFF/Chunks.cpp
|
||||
@@ -99,6 +99,8 @@ static void applyBranch20T(uint8_t *Off, int32_t V) {
|
||||
}
|
||||
|
||||
static void applyBranch24T(uint8_t *Off, int32_t V) {
|
||||
+ if (!isInt<25>(V))
|
||||
+ fatal("relocation out of range");
|
||||
uint32_t S = V < 0 ? 1 : 0;
|
||||
uint32_t J1 = ((~V >> 23) & 1) ^ S;
|
||||
uint32_t J2 = ((~V >> 22) & 1) ^ S;
|
||||
diff --git a/test/COFF/Inputs/far-arm-thumb-abs.s b/test/COFF/Inputs/far-arm-thumb-abs.s
|
||||
new file mode 100644
|
||||
index 0000000..9f1b59a
|
||||
--- /dev/null
|
||||
+++ b/test/COFF/Inputs/far-arm-thumb-abs.s
|
||||
@@ -0,0 +1,2 @@
|
||||
+.global too_far1
|
||||
+too_far1 = 0x1401004
|
||||
diff --git a/test/COFF/arm-thumb-branch-error.s b/test/COFF/arm-thumb-branch-error.s
|
||||
new file mode 100644
|
||||
index 0000000..00b835c
|
||||
--- /dev/null
|
||||
+++ b/test/COFF/arm-thumb-branch-error.s
|
||||
@@ -0,0 +1,10 @@
|
||||
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %s -o %t
|
||||
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %S/Inputs/far-arm-thumb-abs.s -o %tfar
|
||||
+// RUN: not lld-link -entry:_start -subsystem:console %t %tfar -out:%t2 2>&1 | FileCheck %s
|
||||
+// REQUIRES: arm
|
||||
+ .syntax unified
|
||||
+ .globl _start
|
||||
+_start:
|
||||
+ bl too_far1
|
||||
+
|
||||
+// CHECK: relocation out of range
|
||||
--
|
||||
2.7.4
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user