mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
Vendor import of lld trunk r321530:
https://llvm.org/svn/llvm-project/lld/trunk@321530
This commit is contained in:
parent
e30c72b844
commit
ae1a339de3
25 changed files with 253 additions and 63 deletions
|
|
@ -174,6 +174,7 @@ struct Configuration {
|
|||
bool HighEntropyVA = false;
|
||||
bool AppContainer = false;
|
||||
bool MinGW = false;
|
||||
bool WarnLocallyDefinedImported = true;
|
||||
};
|
||||
|
||||
extern Configuration *Config;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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">;
|
||||
|
|
|
|||
|
|
@ -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()) +
|
||||
")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
72
test/COFF/ignore4217.yaml
Normal 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
|
||||
...
|
||||
4
test/ELF/Inputs/writable-sec-plt-reloc.s
Normal file
4
test/ELF/Inputs/writable-sec-plt-reloc.s
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.global foo
|
||||
.type foo, @function
|
||||
foo:
|
||||
retq
|
||||
5
test/ELF/Inputs/znotext-copy-relocations.s
Normal file
5
test/ELF/Inputs/znotext-copy-relocations.s
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.global foo
|
||||
.type foo,@object
|
||||
.size foo, 8
|
||||
foo:
|
||||
.quad 42
|
||||
5
test/ELF/Inputs/znotext-plt-relocations-protected.s
Normal file
5
test/ELF/Inputs/znotext-plt-relocations-protected.s
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.global foo
|
||||
.type foo,@function
|
||||
.protected foo
|
||||
foo:
|
||||
nop
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
14
test/ELF/writable-sec-plt-reloc.s
Normal file
14
test/ELF/writable-sec-plt-reloc.s
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 - .
|
||||
|
|
|
|||
16
test/ELF/znotext-copy-relocation.s
Normal file
16
test/ELF/znotext-copy-relocation.s
Normal 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
|
||||
11
test/ELF/znotext-plt-relocations-protected.s
Normal file
11
test/ELF/znotext-plt-relocations-protected.s
Normal 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
|
||||
16
test/ELF/znotext-weak-undef.s
Normal file
16
test/ELF/znotext-weak-undef.s
Normal 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
|
||||
Loading…
Reference in a new issue