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:
Martin Storsjö authored and Martin Storsjo committed 2016-08-10 14:52:16 +03:00
1 parent 3eb63bea3d
commit 93a77a441a
5 files changed
+341 -65

No files matched your search

+57 -65
View File
@@ -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
+61
View File
@@ -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
+82
View File
@@ -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
+64
View File
@@ -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
+77
View File
@@ -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