Vendor import of lld trunk r321530:

https://llvm.org/svn/llvm-project/lld/trunk@321530
This commit is contained in:
Dimitry Andric 2017-12-28 21:23:25 +00:00
parent e30c72b844
commit ae1a339de3
25 changed files with 253 additions and 63 deletions

View file

@ -174,6 +174,7 @@ struct Configuration {
bool HighEntropyVA = false;
bool AppContainer = false;
bool MinGW = false;
bool WarnLocallyDefinedImported = true;
};
extern Configuration *Config;

View file

@ -227,7 +227,7 @@ static bool isDecorated(StringRef Sym) {
void LinkerDriver::parseDirectives(StringRef S) {
ArgParser Parser;
// .drectve is always tokenized using Windows shell rules.
opt::InputArgList Args = Parser.parse(S);
opt::InputArgList Args = Parser.parseDirectives(S);
for (auto *Arg : Args) {
switch (Arg->getOption().getUnaliasedOption().getID()) {
@ -245,6 +245,13 @@ void LinkerDriver::parseDirectives(StringRef S) {
Config->Entry = addUndefined(mangle(Arg->getValue()));
break;
case OPT_export: {
// If a common header file contains dllexported function
// declarations, many object files may end up with having the
// same /EXPORT options. In order to save cost of parsing them,
// we dedup them first.
if (!DirectivesExports.insert(Arg->getValue()).second)
break;
Export E = parseExport(Arg->getValue());
if (Config->Machine == I386 && Config->MinGW) {
if (!isDecorated(E.Name))
@ -795,6 +802,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
SearchPaths.push_back(Arg->getValue());
addLibSearchPaths();
// Handle /ignore
for (auto *Arg : Args.filtered(OPT_ignore)) {
if (StringRef(Arg->getValue()) == "4217")
Config->WarnLocallyDefinedImported = false;
// Other warning numbers are ignored.
}
// Handle /out
if (auto *Arg = Args.getLastArg(OPT_out))
Config->OutputFile = Arg->getValue();

View file

@ -16,6 +16,7 @@
#include "lld/Common/Reproduce.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Option/Arg.h"
@ -54,6 +55,10 @@ public:
// Tokenizes a given string and then parses as command line options.
llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
// Tokenizes a given string and then parses as command line options in
// .drectve section.
llvm::opt::InputArgList parseDirectives(StringRef S);
private:
// Parses command line options.
llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
@ -123,6 +128,8 @@ private:
std::list<std::function<void()>> TaskQueue;
std::vector<StringRef> FilePaths;
std::vector<MemoryBufferRef> Resources;
llvm::StringSet<> DirectivesExports;
};
// Functions below this line are defined in DriverUtils.cpp.

View file

@ -750,6 +750,22 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
return Args;
}
// Tokenizes and parses a given string as command line in .drective section.
opt::InputArgList ArgParser::parseDirectives(StringRef S) {
// Make InputArgList from string vectors.
unsigned MissingIndex;
unsigned MissingCount;
opt::InputArgList Args =
Table.ParseArgs(tokenize(S), MissingIndex, MissingCount);
if (MissingCount)
fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");
for (auto *Arg : Args.filtered(OPT_UNKNOWN))
warn("ignoring unknown argument: " + Arg->getSpelling());
return Args;
}
// link.exe has an interesting feature. If LINK or _LINK_ environment
// variables exist, their contents are handled as command line strings.
// So you can pass extra arguments using them.

View file

@ -29,6 +29,7 @@ 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 heap : P<"heap", "Size of the heap">;
def ignore : P<"ignore", "Specify warning codes to ignore">;
def implib : P<"implib", "Import library name">;
def libpath : P<"libpath", "Additional library search path">;
def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">;
@ -155,7 +156,6 @@ def fastfail : F<"fastfail">;
def delay : QF<"delay">;
def errorreport : QF<"errorreport">;
def idlout : QF<"idlout">;
def ignore : QF<"ignore">;
def maxilksize : QF<"maxilksize">;
def natvis : QF<"natvis">;
def pdbaltpath : QF<"pdbaltpath">;

View file

@ -117,9 +117,10 @@ void SymbolTable::reportRemainingUndefines() {
for (Symbol *B : Config->GCRoot) {
if (Undefs.count(B))
errorOrWarn("<root>: undefined symbol: " + B->getName());
if (Symbol *Imp = LocalImports.lookup(B))
warn("<root>: locally defined symbol imported: " + Imp->getName() +
" (defined in " + toString(Imp->getFile()) + ")");
if (Config->WarnLocallyDefinedImported)
if (Symbol *Imp = LocalImports.lookup(B))
warn("<root>: locally defined symbol imported: " + Imp->getName() +
" (defined in " + toString(Imp->getFile()) + ")");
}
for (ObjFile *File : ObjFile::Instances) {
@ -128,9 +129,11 @@ void SymbolTable::reportRemainingUndefines() {
continue;
if (Undefs.count(Sym))
errorOrWarn(toString(File) + ": undefined symbol: " + Sym->getName());
if (Symbol *Imp = LocalImports.lookup(Sym))
warn(toString(File) + ": locally defined symbol imported: " +
Imp->getName() + " (defined in " + toString(Imp->getFile()) + ")");
if (Config->WarnLocallyDefinedImported)
if (Symbol *Imp = LocalImports.lookup(Sym))
warn(toString(File) + ": locally defined symbol imported: " +
Imp->getName() + " (defined in " + toString(Imp->getFile()) +
")");
}
}
}

View file

@ -192,9 +192,9 @@ void X86::writePltHeader(uint8_t *Buf) const {
}
const uint8_t PltData[] = {
0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushl (GOTPLT+4)
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *(GOTPLT+8)
0x90, 0x90, 0x90, 0x90 // nop
0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4)
0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8)
0x90, 0x90, 0x90, 0x90, // nop
};
memcpy(Buf, PltData, sizeof(PltData));
uint32_t GotPlt = InX::GotPlt->getVA();
@ -206,9 +206,9 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Inst[] = {
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, // jmp *foo_in_GOT|*foo@GOT(%ebx)
0x68, 0x00, 0x00, 0x00, 0x00, // pushl $reloc_offset
0xe9, 0x00, 0x00, 0x00, 0x00 // jmp .PLT0@PC
0xff, 0x00, 0, 0, 0, 0, // jmp *foo_in_GOT or jmp *foo@GOT(%ebx)
0x68, 0, 0, 0, 0, // pushl $reloc_offset
0xe9, 0, 0, 0, 0, // jmp .PLT0@PC
};
memcpy(Buf, Inst, sizeof(Inst));
@ -318,7 +318,7 @@ void X86::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
// subl $x@ntpoff,%eax
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 // subl 0(%ebx), %eax
0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
write32le(Loc + 5, Val);
@ -333,7 +333,7 @@ void X86::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {
// addl x@gotntpoff(%ebx), %eax
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
0x03, 0x83, 0x00, 0x00, 0x00, 0x00 // addl 0(%ebx), %eax
0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
write32le(Loc + 5, Val);
@ -394,7 +394,7 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
const uint8_t Inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
0x90, // nop
0x8d, 0x74, 0x26, 0x00 // leal 0(%esi,1),%esi
0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi
};
memcpy(Loc - 2, Inst, sizeof(Inst));
}

View file

@ -129,9 +129,9 @@ void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
const uint8_t PltData[] = {
0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOTPLT+8(%rip)
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOTPLT+16(%rip)
0x0f, 0x1f, 0x40, 0x00 // nop
0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
0x0f, 0x1f, 0x40, 0x00, // nop
};
memcpy(Buf, PltData, sizeof(PltData));
uint64_t GotPlt = InX::GotPlt->getVA();
@ -145,9 +145,9 @@ void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {
const uint8_t Inst[] = {
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
0x68, 0, 0, 0, 0, // pushq <relocation index>
0xe9, 0, 0, 0, 0, // jmpq plt[0]
};
memcpy(Buf, Inst, sizeof(Inst));
@ -175,7 +175,7 @@ void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type,
// lea x@tpoff,%rax
const uint8_t Inst[] = {
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 // lea x@tpoff,%rax
0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
@ -198,7 +198,7 @@ void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type,
// addq x@tpoff,%rax
const uint8_t Inst[] = {
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
0x48, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00 // addq x@tpoff,%rax
0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@tpoff,%rax
};
memcpy(Loc - 4, Inst, sizeof(Inst));
@ -274,9 +274,9 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
}
const uint8_t Inst[] = {
0x66, 0x66, // .word 0x6666
0x66, // .byte 0x66
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 // mov %fs:0,%rax
0x66, 0x66, // .word 0x6666
0x66, // .byte 0x66
0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
};
memcpy(Loc - 3, Inst, sizeof(Inst));
}

View file

@ -581,44 +581,38 @@ static RelExpr getPltExpr(Symbol &Sym, RelExpr Expr, bool &IsConstant) {
return toPlt(Expr);
}
// This modifies the expression if we can use a copy relocation or point the
// symbol to the PLT.
template <class ELFT>
static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
InputSectionBase &S, uint64_t RelOff,
bool &IsConstant) {
// We can create any dynamic relocation if a section is simply writable.
if (S.Flags & SHF_WRITE)
return Expr;
// Or, if we are allowed to create dynamic relocations against
// read-only sections (i.e. when "-z notext" is given),
// we can create a dynamic relocation as we want, too.
if (!Config->ZText) {
// We use PLT for relocations that may overflow in runtime,
// see comment for getPltExpr().
if (Sym.isFunc() && !Target->isPicRel(Type))
return getPltExpr(Sym, Expr, IsConstant);
return Expr;
}
// If a relocation can be applied at link-time, we don't need to
// create a dynamic relocation in the first place.
if (IsConstant)
return Expr;
// If we got here we know that this relocation would require the dynamic
// linker to write a value to read only memory.
// If the relocation is to a weak undef, give up on it and produce a
// non preemptible 0.
if (Sym.isUndefWeak()) {
// If the relocation is to a weak undef, and we are producing
// executable, give up on it and produce a non preemptible 0.
if (!Config->Shared && Sym.isUndefWeak()) {
Sym.IsPreemptible = false;
IsConstant = true;
return Expr;
}
// We can create any dynamic relocation supported by the dynamic linker if a
// section is writable or we are passed -z notext.
bool CanWrite = (S.Flags & SHF_WRITE) || !Config->ZText;
if (CanWrite && Target->isPicRel(Type))
return Expr;
// If we got here we know that this relocation would require the dynamic
// linker to write a value to read only memory or use an unsupported
// relocation.
// We can hack around it if we are producing an executable and
// the refered symbol can be preemepted to refer to the executable.
if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
if (!CanWrite && (Config->Shared || (Config->Pic && !isRelExpr(Expr)))) {
error(
"can't create dynamic relocation " + toString(Type) + " against " +
(Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +
@ -627,6 +621,11 @@ static RelExpr adjustExpr(Symbol &Sym, RelExpr Expr, RelType Type,
return Expr;
}
// Copy relocations are only possible if we are creating an executable and the
// symbol is shared.
if (!Sym.isShared() || Config->Shared)
return Expr;
if (Sym.getVisibility() != STV_DEFAULT) {
error("cannot preempt symbol: " + toString(Sym) +
getLocation(S, Sym, RelOff));

View file

@ -115,11 +115,19 @@ void ScriptLexer::tokenize(MemoryBufferRef MB) {
continue;
}
// ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||
S.startswith(">=")) {
Vec.push_back(S.substr(0, 2));
S = S.substr(2);
continue;
}
// Unquoted token. This is more relaxed than tokens in C-like language,
// so that you can write "file-name.cpp" as one bare token, for example.
size_t Pos = S.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789_.$/\\~=+[]*?-!<>^:");
"0123456789_.$/\\~=+[]*?-!^:");
// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.

View file

@ -151,6 +151,7 @@ static ExprValue add(ExprValue A, ExprValue B) {
}
static ExprValue sub(ExprValue A, ExprValue B) {
// The distance between two symbols in sections is absolute.
if (!A.isAbsolute() && !B.isAbsolute())
return A.getValue() - B.getValue();
return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};
@ -707,8 +708,6 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
if (consume(">"))
Cmd->MemoryRegionName = next();
else if (peek().startswith(">"))
Cmd->MemoryRegionName = next().drop_front();
Cmd->Phdrs = readOutputSectionPhdrs();

72
test/COFF/ignore4217.yaml Normal file
View file

@ -0,0 +1,72 @@
# Tests that /ignore:4217 suppresses "locally defined symbol imported" warnings.
# RUN: yaml2obj < %s > %t.obj
# RUN: lld-link -entry:main -out:%t.exe %t.obj 2>&1 \
# RUN: | FileCheck -check-prefix=WARNINGS %s
# RUN: lld-link -ignore:4217 -entry:main -out:%t.exe %t.obj 2>&1 \
# RUN: | FileCheck -allow-empty -check-prefix=SUPPRESSED %s
# WARNINGS: locally defined symbol imported
# SUPPRESSED-NOT: locally defined symbol imported
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 16
SectionData: B82A000000C3662E0F1F8400000000004883EC28C744242400000000E800000000904883C428C3
Relocations:
- VirtualAddress: 29
SymbolName: __imp_foo
Type: IMAGE_REL_AMD64_REL32
- Name: .data
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
Alignment: 4
SectionData: ''
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 39
NumberOfRelocations: 1
NumberOfLinenumbers: 0
CheckSum: 3087210877
Number: 1
- Name: .data
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 0
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 2
- Name: foo
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: main
Value: 16
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: __imp_foo
Value: 0
SectionNumber: 0
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View file

@ -0,0 +1,4 @@
.global foo
.type foo, @function
foo:
retq

View file

@ -0,0 +1,5 @@
.global foo
.type foo,@object
.size foo, 8
foo:
.quad 42

View file

@ -0,0 +1,5 @@
.global foo
.type foo,@function
.protected foo
foo:
nop

View file

@ -21,4 +21,4 @@ _start:
// 69636 = 0x11004 = next instruction
// CHECK: 11000: {{.*}} bl #0
// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8>
// CHECK-NEXT: 11008: {{.*}} b.w #0 <_start+0xC>
// CHECK-NEXT: 11008: {{.*}} b.w #0 <_start+0xc>

View file

@ -32,7 +32,7 @@ _start:
// CHECK: 11000: {{.*}} b #-4 <_start+0x4>
// CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8>
// blx is transformed into bl so we don't change state
// CHECK-NEXT: 11008: {{.*}} bl #-4 <_start+0xC>
// CHECK-NEXT: 11008: {{.*}} bl #-4 <_start+0xc>
// CHECK-NEXT: 1100c: {{.*}} movt r0, #0
// CHECK-NEXT: 11010: {{.*}} movw r0, #0
// CHECK: 11014: {{.*}} .word 0x00000000

View file

@ -102,10 +102,10 @@
// DISASM-NEXT: .plt:
// DISASM-NEXT: 11020: ff 25 00 20 01 00 jmpl *73728
// DISASM-NEXT: 11026: 68 10 00 00 00 pushl $16
// DISASM-NEXT: 1102b: e9 e0 ff ff ff jmp -32 <_start+0xE>
// DISASM-NEXT: 1102b: e9 e0 ff ff ff jmp -32 <_start+0xe>
// DISASM-NEXT: 11030: ff 25 04 20 01 00 jmpl *73732
// DISASM-NEXT: 11036: 68 18 00 00 00 pushl $24
// DISASM-NEXT: 1103b: e9 d0 ff ff ff jmp -48 <_start+0xE>
// DISASM-NEXT: 1103b: e9 d0 ff ff ff jmp -48 <_start+0xe>
.text
.type foo STT_GNU_IFUNC

View file

@ -102,10 +102,10 @@
// DISASM-NEXT: .plt:
// DISASM-NEXT: 201020: {{.*}} jmpq *4058(%rip)
// DISASM-NEXT: 201026: {{.*}} pushq $0
// DISASM-NEXT: 20102b: {{.*}} jmp -32 <_start+0xE>
// DISASM-NEXT: 20102b: {{.*}} jmp -32 <_start+0xe>
// DISASM-NEXT: 201030: {{.*}} jmpq *4050(%rip)
// DISASM-NEXT: 201036: {{.*}} pushq $1
// DISASM-NEXT: 20103b: {{.*}} jmp -48 <_start+0xE>
// DISASM-NEXT: 20103b: {{.*}} jmp -48 <_start+0xe>
.text
.type foo STT_GNU_IFUNC

View file

@ -0,0 +1,14 @@
# REQUIRES: x86
# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
# RUN: llvm-mc %p/Inputs/writable-sec-plt-reloc.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
# RUN: ld.lld %t2.o -o %t2.so -shared
# RUN: ld.lld %t.o %t2.so -o %t
# RUN: llvm-readelf --symbols -r %t | FileCheck %s
# CHECK: R_X86_64_JUMP_SLOT {{.*}} foo + 0
# CHECK: 0000000000201010 0 FUNC GLOBAL DEFAULT UND foo
.section .bar,"awx"
.global _start
_start:
call foo

View file

@ -2,12 +2,12 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld %t2.o -shared -o %t2.so
// RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s
// RUN: not ld.lld -shared %t.o %t2.so -o %t 2>&1 | FileCheck %s
.global _start
_start:
.data
.long bar
.long zed
// CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC

View file

@ -2,7 +2,7 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld %t2.o -shared -o %t2.so
// RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s
// RUN: not ld.lld -shared %t.o %t2.so -o %t 2>&1 | FileCheck %s
// CHECK: relocation R_X86_64_PC32 cannot be used against shared object; recompile with -fPIC
// CHECK: >>> defined in {{.*}}.so
@ -11,4 +11,4 @@
.global _start
_start:
.data
.long bar - .
.long zed - .

View file

@ -0,0 +1,16 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/znotext-copy-relocations.s -o %t2.o
# RUN: ld.lld %t2.o -o %t2.so -shared
# RUN: ld.lld -z notext %t.o %t2.so -o %t
# RUN: llvm-readobj -r %t | FileCheck %s
# CHECK: Relocations [
# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
# CHECK-NEXT: R_X86_64_COPY foo 0x0
# CHECK-NEXT: }
# CHECK-NEXT: ]
.global _start
_start:
.long foo

View file

@ -0,0 +1,11 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/znotext-plt-relocations-protected.s -o %t2.o
# RUN: ld.lld %t2.o -o %t2.so -shared
# RUN: not ld.lld -z notext %t.o %t2.so -o %t 2>&1 | FileCheck %s
# CHECK: error: cannot preempt symbol: foo
.global _start
_start:
callq foo

View file

@ -0,0 +1,16 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
# RUN: not ld.lld -z notext -shared %t.o -o %t 2>&1 | FileCheck %s
# CHECK: relocation R_X86_64_32 cannot be used against shared object; recompile with -fPIC
# RUN: ld.lld -z notext %t.o -o %t
# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=EXE
# EXE: Relocations [
# EXE-NEXT: ]
.text
.global foo
.weak foo
_start:
mov $foo,%eax