aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt7
-rw-r--r--COFF/CMakeLists.txt2
-rw-r--r--COFF/Chunks.cpp2
-rw-r--r--COFF/Chunks.h4
-rw-r--r--COFF/Config.h7
-rw-r--r--COFF/DLL.cpp21
-rw-r--r--COFF/Driver.cpp2
-rw-r--r--COFF/DriverUtils.cpp31
-rw-r--r--COFF/InputFiles.cpp1
-rw-r--r--COFF/Writer.cpp17
-rw-r--r--ELF/CMakeLists.txt2
-rw-r--r--ELF/Driver.cpp62
-rw-r--r--ELF/Driver.h8
-rw-r--r--ELF/DriverUtils.cpp10
-rw-r--r--ELF/InputFiles.cpp15
-rw-r--r--ELF/InputFiles.h7
-rw-r--r--ELF/InputSection.cpp33
-rw-r--r--ELF/InputSection.h9
-rw-r--r--ELF/LinkerScript.cpp2
-rw-r--r--ELF/MarkLive.cpp15
-rw-r--r--ELF/Options.td4
-rw-r--r--ELF/OutputSections.cpp174
-rw-r--r--ELF/OutputSections.h23
-rw-r--r--ELF/SymbolTable.cpp49
-rw-r--r--ELF/SymbolTable.h28
-rw-r--r--ELF/Symbols.cpp24
-rw-r--r--ELF/Symbols.h11
-rw-r--r--ELF/Target.cpp178
-rw-r--r--ELF/Target.h10
-rw-r--r--ELF/Writer.cpp124
-rw-r--r--lib/Config/CMakeLists.txt6
-rw-r--r--lib/Core/CMakeLists.txt6
-rw-r--r--lib/Driver/CMakeLists.txt7
-rw-r--r--lib/Driver/GnuLdDriver.cpp1
-rw-r--r--lib/ReaderWriter/CMakeLists.txt6
-rw-r--r--lib/ReaderWriter/ELF/AArch64/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp34
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h41
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp41
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h36
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp19
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h31
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp32
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h32
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp65
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h80
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt13
-rw-r--r--lib/ReaderWriter/ELF/ARM/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/CMakeLists.txt3
-rw-r--r--lib/ReaderWriter/ELF/ELFLinkingContext.cpp2
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/Mips/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/X86/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/X86_64/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm64.cpp16
-rw-r--r--lib/ReaderWriter/MachO/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h3
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp33
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp6
-rw-r--r--lib/ReaderWriter/YAML/CMakeLists.txt2
-rw-r--r--test/COFF/export.test11
-rw-r--r--test/ELF/Inputs/aarch64-condb-reloc.s17
-rw-r--r--test/ELF/Inputs/aarch64-tls-ie.s19
-rw-r--r--test/ELF/Inputs/aarch64-tstbr14-reloc.s12
-rw-r--r--test/ELF/Inputs/mips-gp-disp.sobin0 -> 131832 bytes
-rw-r--r--test/ELF/Inputs/wrap.s4
-rw-r--r--test/ELF/aarch64-condb-reloc.s99
-rw-r--r--test/ELF/aarch64-gnu-ifunc-nosym.s29
-rw-r--r--test/ELF/aarch64-gnu-ifunc.s144
-rw-r--r--test/ELF/aarch64-tls-ie.s49
-rw-r--r--test/ELF/aarch64-tstbr14-reloc.s96
-rw-r--r--test/ELF/amdgpu-entry.s16
-rw-r--r--test/ELF/amdgpu-globals.s138
-rw-r--r--test/ELF/amdgpu-kernels.s63
-rw-r--r--test/ELF/basic-aarch64.s2
-rw-r--r--test/ELF/basic-mips.s6
-rw-r--r--test/ELF/basic-ppc.s296
-rw-r--r--test/ELF/basic.s2
-rw-r--r--test/ELF/basic32.s2
-rw-r--r--test/ELF/basic64be.s4
-rw-r--r--test/ELF/discard-none.s4
-rw-r--r--test/ELF/linkerscript-sections.s8
-rw-r--r--test/ELF/mips-gp-disp.s34
-rw-r--r--test/ELF/ppc-relocs.s30
-rw-r--r--test/ELF/relocation-copy.s16
-rw-r--r--test/ELF/string-table.s9
-rw-r--r--test/ELF/wrap.s19
-rw-r--r--test/lit.cfg2
-rw-r--r--test/mach-o/arm64-reloc-negDelta32-fixup.yaml4
-rw-r--r--test/mach-o/do-not-emit-unwind-fde-arm64.yaml208
-rw-r--r--test/mach-o/parse-data-relocs-arm64.yaml68
-rw-r--r--test/old-elf/AMDGPU/hsa.test53
93 files changed, 2027 insertions, 850 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b64301d1ad8..7458de08fc16 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(LLD_INCLUDE_DIR ${LLD_SOURCE_DIR}/include )
set(LLD_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# Compute the LLD version from the LLVM version.
@@ -86,6 +87,12 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
)
endif()
+macro(add_lld_library name)
+ add_llvm_library(${name} ${ARGN})
+ set_target_properties(${name} PROPERTIES FOLDER "lld libraries")
+endmacro(add_lld_library)
+
+
add_subdirectory(lib)
add_subdirectory(tools)
diff --git a/COFF/CMakeLists.txt b/COFF/CMakeLists.txt
index 78dc34eff96e..3f31ba9ba1fb 100644
--- a/COFF/CMakeLists.txt
+++ b/COFF/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(COFFOptionsTableGen)
-add_llvm_library(lldCOFF
+add_lld_library(lldCOFF
Chunks.cpp
DLL.cpp
Driver.cpp
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
index 50bf55be269b..f9f768d69866 100644
--- a/COFF/Chunks.cpp
+++ b/COFF/Chunks.cpp
@@ -310,7 +310,7 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const {
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
// Block header consists of 4 byte page RVA and 4 byte block size.
// Each entry is 2 byte. Last entry may be padding.
- Data.resize(RoundUpToAlignment((End - Begin) * 2 + 8, 4));
+ Data.resize(align((End - Begin) * 2 + 8, 4));
uint8_t *P = Data.data();
write32le(P, Page);
write32le(P + 4, Data.size());
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index 60b8e76f8230..274135516eb9 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -326,6 +326,10 @@ public:
uint8_t Type;
};
+inline uint64_t align(uint64_t Value, uint64_t Align) {
+ return llvm::RoundUpToAlignment(Value, Align);
+}
+
} // namespace coff
} // namespace lld
diff --git a/COFF/Config.h b/COFF/Config.h
index 409ede648636..9cfccadba5fa 100644
--- a/COFF/Config.h
+++ b/COFF/Config.h
@@ -25,6 +25,7 @@ using llvm::COFF::WindowsSubsystem;
using llvm::StringRef;
class DefinedAbsolute;
class DefinedRelative;
+class StringChunk;
class Undefined;
// Short aliases.
@@ -42,6 +43,12 @@ struct Export {
bool Data = false;
bool Private = false;
+ // If an export is a form of /export:foo=dllname.bar, that means
+ // that foo should be exported as an alias to bar in the DLL.
+ // ForwardTo is set to "dllname.bar" part. Usually empty.
+ StringRef ForwardTo;
+ StringChunk *ForwardChunk = nullptr;
+
// True if this /export option was in .drectves section.
bool Directives = false;
StringRef SymbolName;
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp
index 40ca5cf61dc2..8f3383d75c7b 100644
--- a/COFF/DLL.cpp
+++ b/COFF/DLL.cpp
@@ -45,7 +45,7 @@ public:
size_t getSize() const override {
// Starts with 2 byte Hint field, followed by a null-terminated string,
// ends with 0 or 1 byte padding.
- return RoundUpToAlignment(Name.size() + 3, 2);
+ return align(Name.size() + 3, 2);
}
void writeTo(uint8_t *Buf) const override {
@@ -320,8 +320,12 @@ public:
void writeTo(uint8_t *Buf) const override {
for (Export &E : Config->Exports) {
- auto *D = cast<Defined>(E.Sym->repl());
- write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
+ uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
+ if (E.ForwardChunk) {
+ write32le(P, E.ForwardChunk->getRVA());
+ } else {
+ write32le(P, cast<Defined>(E.Sym->repl())->getRVA());
+ }
}
}
@@ -539,6 +543,15 @@ EdataContents::EdataContents() {
for (Export &E : Config->Exports)
if (!E.Noname)
Names.push_back(new StringChunk(E.ExportName));
+
+ std::vector<Chunk *> Forwards;
+ for (Export &E : Config->Exports) {
+ if (E.ForwardTo.empty())
+ continue;
+ E.ForwardChunk = new StringChunk(E.ForwardTo);
+ Forwards.push_back(E.ForwardChunk);
+ }
+
auto *NameTab = new NamePointersChunk(Names);
auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
@@ -550,6 +563,8 @@ EdataContents::EdataContents() {
Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
for (Chunk *C : Names)
Chunks.push_back(std::unique_ptr<Chunk>(C));
+ for (Chunk *C : Forwards)
+ Chunks.push_back(std::unique_ptr<Chunk>(C));
}
} // namespace coff
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index f528dafd9857..4cacf0ff552a 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -586,6 +586,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Windows specific -- Make sure we resolve all dllexported symbols.
for (Export &E : Config->Exports) {
+ if (!E.ForwardTo.empty())
+ continue;
E.Sym = addUndefined(E.Name);
if (!E.Directives)
Symtab.mangleMaybe(E.Sym);
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
index 391a8ab66420..014fee7fefd7 100644
--- a/COFF/DriverUtils.cpp
+++ b/COFF/DriverUtils.cpp
@@ -321,7 +321,8 @@ void createSideBySideManifest() {
}
// Parse a string in the form of
-// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]".
+// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]"
+// or "<name>=<dllname>.<name>".
// Used for parsing /export arguments.
Export parseExport(StringRef Arg) {
Export E;
@@ -329,12 +330,25 @@ Export parseExport(StringRef Arg) {
std::tie(E.Name, Rest) = Arg.split(",");
if (E.Name.empty())
goto err;
+
if (E.Name.find('=') != StringRef::npos) {
- std::tie(E.ExtName, E.Name) = E.Name.split("=");
+ StringRef X, Y;
+ std::tie(X, Y) = E.Name.split("=");
+
+ // If "<name>=<dllname>.<name>".
+ if (Y.find(".") != StringRef::npos) {
+ E.Name = X;
+ E.ForwardTo = Y;
+ return E;
+ }
+
+ E.ExtName = X;
+ E.Name = Y;
if (E.Name.empty())
goto err;
}
+ // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]"
while (!Rest.empty()) {
StringRef Tok;
std::tie(Tok, Rest) = Rest.split(",");
@@ -388,15 +402,22 @@ void fixupExports() {
}
for (Export &E : Config->Exports) {
- if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
+ if (!E.ForwardTo.empty()) {
+ E.SymbolName = E.Name;
+ } else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
E.SymbolName = U->getName();
} else {
E.SymbolName = E.Sym->getName();
}
}
- for (Export &E : Config->Exports)
- E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+ for (Export &E : Config->Exports) {
+ if (!E.ForwardTo.empty()) {
+ E.ExportName = undecorate(E.Name);
+ } else {
+ E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+ }
+ }
// Uniquefy by name.
std::map<StringRef, Export *> Map;
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
index 23fc2a085122..23af1e89c34d 100644
--- a/COFF/InputFiles.cpp
+++ b/COFF/InputFiles.cpp
@@ -23,7 +23,6 @@
using namespace llvm::COFF;
using namespace llvm::object;
using namespace llvm::support::endian;
-using llvm::RoundUpToAlignment;
using llvm::Triple;
using llvm::support::ulittle32_t;
using llvm::sys::fs::file_magic;
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
index a74b316b87a4..5575c8d6b320 100644
--- a/COFF/Writer.cpp
+++ b/COFF/Writer.cpp
@@ -163,13 +163,13 @@ void OutputSection::addChunk(Chunk *C) {
Chunks.push_back(C);
C->setOutputSection(this);
uint64_t Off = Header.VirtualSize;
- Off = RoundUpToAlignment(Off, C->getAlign());
+ Off = align(Off, C->getAlign());
C->setRVA(Off);
C->setOutputSectionOff(Off);
Off += C->getSize();
Header.VirtualSize = Off;
if (C->hasData())
- Header.SizeOfRawData = RoundUpToAlignment(Off, SectorSize);
+ Header.SizeOfRawData = align(Off, SectorSize);
}
void OutputSection::addPermissions(uint32_t C) {
@@ -448,15 +448,14 @@ void Writer::createSymbolAndStringTable() {
OutputSection *LastSection = OutputSections.back();
// We position the symbol table to be adjacent to the end of the last section.
uint64_t FileOff =
- LastSection->getFileOff() +
- RoundUpToAlignment(LastSection->getRawSize(), SectorSize);
+ LastSection->getFileOff() + align(LastSection->getRawSize(), SectorSize);
if (!OutputSymtab.empty()) {
PointerToSymbolTable = FileOff;
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
}
if (!Strtab.empty())
FileOff += Strtab.size() + 4;
- FileSize = RoundUpToAlignment(FileOff, SectorSize);
+ FileSize = align(FileOff, SectorSize);
}
// Visits all sections to assign incremental, non-overlapping RVAs and
@@ -467,7 +466,7 @@ void Writer::assignAddresses() {
sizeof(coff_section) * OutputSections.size();
SizeOfHeaders +=
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
- SizeOfHeaders = RoundUpToAlignment(SizeOfHeaders, SectorSize);
+ SizeOfHeaders = align(SizeOfHeaders, SectorSize);
uint64_t RVA = 0x1000; // The first page is kept unmapped.
FileSize = SizeOfHeaders;
// Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
@@ -481,10 +480,10 @@ void Writer::assignAddresses() {
addBaserels(Sec);
Sec->setRVA(RVA);
Sec->setFileOffset(FileSize);
- RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
- FileSize += RoundUpToAlignment(Sec->getRawSize(), SectorSize);
+ RVA += align(Sec->getVirtualSize(), PageSize);
+ FileSize += align(Sec->getRawSize(), SectorSize);
}
- SizeOfImage = SizeOfHeaders + RoundUpToAlignment(RVA - 0x1000, PageSize);
+ SizeOfImage = SizeOfHeaders + align(RVA - 0x1000, PageSize);
}
template <typename PEHeaderTy> void Writer::writeHeader() {
diff --git a/ELF/CMakeLists.txt b/ELF/CMakeLists.txt
index 763275e30caa..3dcb65ff8957 100644
--- a/ELF/CMakeLists.txt
+++ b/ELF/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(ELFOptionsTableGen)
-add_llvm_library(lldELF2
+add_lld_library(lldELF2
Driver.cpp
DriverUtils.cpp
Error.cpp
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 2a3ecfa61586..f00d97851e4a 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -26,10 +26,10 @@ using namespace llvm::object;
using namespace lld;
using namespace lld::elf2;
-Configuration *lld::elf2::Config;
-LinkerDriver *lld::elf2::Driver;
+Configuration *elf2::Config;
+LinkerDriver *elf2::Driver;
-void lld::elf2::link(ArrayRef<const char *> Args) {
+void elf2::link(ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
Config = &C;
@@ -42,9 +42,9 @@ static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
return {ELF32BEKind, EM_MIPS};
if (S == "elf32ltsmip")
return {ELF32LEKind, EM_MIPS};
- if (S == "elf32ppc")
+ if (S == "elf32ppc" || S == "elf32ppc_fbsd")
return {ELF32BEKind, EM_PPC};
- if (S == "elf64ppc")
+ if (S == "elf64ppc" || S == "elf64ppc_fbsd")
return {ELF64BEKind, EM_PPC64};
if (S == "elf_i386")
return {ELF32LEKind, EM_386};
@@ -107,6 +107,24 @@ void LinkerDriver::addFile(StringRef Path) {
}
}
+// Some command line options or some combinations of them are not allowed.
+// This function checks for such errors.
+static void checkOptions(opt::InputArgList &Args) {
+ // Traditional linkers can generate re-linkable object files instead
+ // of executables or DSOs. We don't support that since the feature
+ // does not seem to provide more value than the static archiver.
+ if (Args.hasArg(OPT_relocatable))
+ error("-r option is not supported. Use 'ar' command instead.");
+
+ // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
+ // table which is a relatively new feature.
+ if (Config->EMachine == EM_MIPS && Config->GnuHash)
+ error("The .gnu.hash section is not compatible with the MIPS target.");
+
+ if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty())
+ error("-e option is not valid for AMDGPU.");
+}
+
static StringRef
getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") {
if (auto *Arg = Args.getLastArg(Key))
@@ -125,13 +143,9 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
initSymbols();
opt::InputArgList Args = parseArgs(&Alloc, ArgsArr);
+ readConfigs(Args);
createFiles(Args);
-
- // Traditional linkers can generate re-linkable object files instead
- // of executables or DSOs. We don't support that since the feature
- // does not seem to provide more value than the static archiver.
- if (Args.hasArg(OPT_relocatable))
- error("-r option is not supported. Use 'ar' command instead.");
+ checkOptions(Args);
switch (Config->EKind) {
case ELF32LEKind:
@@ -151,7 +165,8 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
}
}
-void LinkerDriver::createFiles(opt::InputArgList &Args) {
+// Initializes Config members by the command line options.
+void LinkerDriver::readConfigs(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_L))
Config->SearchPaths.push_back(Arg->getValue());
@@ -162,10 +177,9 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
if (auto *Arg = Args.getLastArg(OPT_m)) {
+ // Parse ELF{32,64}{LE,BE} and CPU type.
StringRef S = Arg->getValue();
- std::pair<ELFKind, uint16_t> P = parseEmulation(S);
- Config->EKind = P.first;
- Config->EMachine = P.second;
+ std::tie(Config->EKind, Config->EMachine) = parseEmulation(S);
Config->Emulation = S;
}
@@ -217,7 +231,9 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_undefined))
Config->Undefined.push_back(Arg->getValue());
+}
+void LinkerDriver::createFiles(opt::InputArgList &Args) {
for (auto *Arg : Args) {
switch (Arg->getOption().getID()) {
case OPT_l:
@@ -250,9 +266,6 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
if (Files.empty())
error("no input files.");
-
- if (Config->GnuHash && Config->EMachine == EM_MIPS)
- error("The .gnu.hash section is not compatible with the MIPS target.");
}
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
@@ -261,7 +274,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (!Config->Shared) {
// Add entry symbol.
- if (Config->Entry.empty())
+ //
+ // There is no entry symbol for AMDGPU binaries, so skip adding one to avoid
+ // having and undefined symbol.
+ if (Config->Entry.empty() && Config->EMachine != EM_AMDGPU)
Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
// In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
@@ -288,8 +304,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (Config->EMachine == EM_MIPS) {
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
- // start of function and gp pointer into GOT.
- Config->MipsGpDisp = Symtab.addIgnored("_gp_disp");
+ // start of function and gp pointer into GOT. Use 'strong' variant of
+ // the addIgnored to prevent '_gp_disp' substitution.
+ Config->MipsGpDisp = Symtab.addIgnoredStrong("_gp_disp");
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
// so that it points to an absolute address which is relative to GOT.
@@ -304,6 +321,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (StringRef S : Config->Undefined)
Symtab.addUndefinedOpt(S);
+ for (auto *Arg : Args.filtered(OPT_wrap))
+ Symtab.wrap(Arg->getValue());
+
if (Config->OutputFile.empty())
Config->OutputFile = "a.out";
diff --git a/ELF/Driver.h b/ELF/Driver.h
index bfae2b3f4dfa..720ef46dc710 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -26,14 +26,12 @@ void link(ArrayRef<const char *> Args);
class LinkerDriver {
public:
void main(ArrayRef<const char *> Args);
- void createFiles(llvm::opt::InputArgList &Args);
- template <class ELFT> void link(llvm::opt::InputArgList &Args);
-
void addFile(StringRef Path);
private:
- template <template <class> class T>
- std::unique_ptr<InputFile> createELFInputFile(MemoryBufferRef MB);
+ void readConfigs(llvm::opt::InputArgList &Args);
+ void createFiles(llvm::opt::InputArgList &Args);
+ template <class ELFT> void link(llvm::opt::InputArgList &Args);
llvm::BumpPtrAllocator Alloc;
bool WholeArchive = false;
diff --git a/ELF/DriverUtils.cpp b/ELF/DriverUtils.cpp
index 51b500bebf49..965ed4f00a61 100644
--- a/ELF/DriverUtils.cpp
+++ b/ELF/DriverUtils.cpp
@@ -51,8 +51,8 @@ public:
};
// Parses a given list of options.
-opt::InputArgList lld::elf2::parseArgs(llvm::BumpPtrAllocator *A,
- ArrayRef<const char *> Argv) {
+opt::InputArgList elf2::parseArgs(llvm::BumpPtrAllocator *A,
+ ArrayRef<const char *> Argv) {
// Make InputArgList from string vectors.
ELFOptTable Table;
unsigned MissingIndex;
@@ -79,7 +79,7 @@ opt::InputArgList lld::elf2::parseArgs(llvm::BumpPtrAllocator *A,
return Args;
}
-std::string lld::elf2::findFromSearchPaths(StringRef Path) {
+std::string elf2::findFromSearchPaths(StringRef Path) {
for (StringRef Dir : Config->SearchPaths) {
std::string FullPath = buildSysrootedPath(Dir, Path);
if (sys::fs::exists(FullPath))
@@ -90,7 +90,7 @@ std::string lld::elf2::findFromSearchPaths(StringRef Path) {
// Searches a given library from input search paths, which are filled
// from -L command line switches. Returns a path to an existent library file.
-std::string lld::elf2::searchLibrary(StringRef Path) {
+std::string elf2::searchLibrary(StringRef Path) {
std::vector<std::string> Names;
if (Path[0] == ':') {
Names.push_back(Path.drop_front());
@@ -110,7 +110,7 @@ std::string lld::elf2::searchLibrary(StringRef Path) {
// Makes a path by concatenating Dir and File.
// If Dir starts with '=' the result will be preceded by Sysroot,
// which can be set with --sysroot command line switch.
-std::string lld::elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
+std::string elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
SmallString<128> Path;
if (Dir.startswith("="))
sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index d9df6abbf233..6a908d450f60 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -92,7 +92,9 @@ typename ObjectFile<ELFT>::Elf_Sym_Range ObjectFile<ELFT>::getLocalSymbols() {
}
template <class ELFT> uint32_t ObjectFile<ELFT>::getMipsGp0() const {
- return MipsReginfo ? MipsReginfo->getGp0() : 0;
+ if (MipsReginfo)
+ return MipsReginfo->Reginfo->ri_gp_value;
+ return 0;
}
template <class ELFT>
@@ -132,13 +134,13 @@ StringRef ObjectFile<ELFT>::getShtGroupSignature(const Elf_Shdr &Sec) {
}
template <class ELFT>
-ArrayRef<typename ObjectFile<ELFT>::GroupEntryType>
+ArrayRef<typename ObjectFile<ELFT>::uint32_X>
ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
const ELFFile<ELFT> &Obj = this->ELFObj;
- ErrorOr<ArrayRef<GroupEntryType>> EntriesOrErr =
- Obj.template getSectionContentsAsArray<GroupEntryType>(&Sec);
+ ErrorOr<ArrayRef<uint32_X>> EntriesOrErr =
+ Obj.template getSectionContentsAsArray<uint32_X>(&Sec);
error(EntriesOrErr);
- ArrayRef<GroupEntryType> Entries = *EntriesOrErr;
+ ArrayRef<uint32_X> Entries = *EntriesOrErr;
if (Entries.empty() || Entries[0] != GRP_COMDAT)
error("Unsupported SHT_GROUP format");
return Entries.slice(1);
@@ -187,8 +189,7 @@ void ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &ComdatGroups) {
Sections[I] = &InputSection<ELFT>::Discarded;
if (ComdatGroups.insert(getShtGroupSignature(Sec)).second)
continue;
- for (GroupEntryType E : getShtGroupEntries(Sec)) {
- uint32_t SecIndex = E;
+ for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
if (SecIndex >= Size)
error("Invalid section index in group");
Sections[SecIndex] = &InputSection<ELFT>::Discarded;
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 9c54a9328f80..45d403c0125c 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -91,10 +91,13 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ // uint32 in ELFT's byte order
typedef llvm::support::detail::packed_endian_specific_integral<
- uint32_t, ELFT::TargetEndianness, 2> GroupEntryType;
+ uint32_t, ELFT::TargetEndianness, 2>
+ uint32_X;
+
StringRef getShtGroupSignature(const Elf_Shdr &Sec);
- ArrayRef<GroupEntryType> getShtGroupEntries(const Elf_Shdr &Sec);
+ ArrayRef<uint32_X> getShtGroupEntries(const Elf_Shdr &Sec);
public:
static bool classof(const InputFile *F) {
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index 2548200feb65..f6aa51b47b98 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -52,7 +52,9 @@ InputSectionBase<ELFT>::getOffset(uintX_t Offset) {
case Merge:
return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
case MipsReginfo:
- return cast<MipsReginfoInputSection<ELFT>>(this)->getOffset(Offset);
+ // MIPS .reginfo sections are consumed by the linker,
+ // so it should never be copied to output.
+ llvm_unreachable("MIPS .reginfo reached writeTo().");
}
llvm_unreachable("Invalid section kind");
}
@@ -209,7 +211,6 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
uintX_t SymVA = getSymVA<ELFT>(*Body);
if (Target->relocNeedsPlt(Type, *Body)) {
SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
- Type = Target->getPltRefReloc(Type);
} else if (Target->relocNeedsGot(Type, *Body)) {
SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
if (Body->isTls())
@@ -217,8 +218,13 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
} else if (!Target->needsCopyRel(Type, *Body) &&
isa<SharedSymbol<ELFT>>(*Body)) {
continue;
- } else if (Target->isTlsDynReloc(Type, *Body) ||
- Target->isSizeDynReloc(Type, *Body)) {
+ } else if (Target->isTlsDynReloc(Type, *Body)) {
+ continue;
+ } else if (Target->isSizeReloc(Type) && canBePreempted(Body, false)) {
+ // A SIZE relocation is supposed to set a symbol size, but if a symbol
+ // can be preempted, the size at runtime may be different than link time.
+ // If that's the case, we leave the field alone rather than filling it
+ // with a possibly incorrect value.
continue;
} else if (Config->EMachine == EM_MIPS) {
if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp)
@@ -346,22 +352,13 @@ MergeInputSection<ELFT>::getOffset(uintX_t Offset) {
template <class ELFT>
MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(ObjectFile<ELFT> *F,
- const Elf_Shdr *Header)
- : InputSectionBase<ELFT>(F, Header, InputSectionBase<ELFT>::MipsReginfo) {}
-
-template <class ELFT>
-uint32_t MipsReginfoInputSection<ELFT>::getGeneralMask() const {
- ArrayRef<uint8_t> D = this->getSectionData();
- if (D.size() != sizeof(Elf_Mips_RegInfo))
- error("Invalid size of .reginfo section");
- return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gprmask;
-}
-
-template <class ELFT> uint32_t MipsReginfoInputSection<ELFT>::getGp0() const {
+ const Elf_Shdr *Hdr)
+ : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsReginfo) {
+ // Initialize this->Reginfo.
ArrayRef<uint8_t> D = this->getSectionData();
- if (D.size() != sizeof(Elf_Mips_RegInfo))
+ if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>))
error("Invalid size of .reginfo section");
- return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gp_value;
+ Reginfo = reinterpret_cast<const Elf_Mips_RegInfo<ELFT> *>(D.data());
}
template <class ELFT>
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index 24491a2e17c0..26956c72a960 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -177,16 +177,13 @@ public:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
template <class ELFT>
class MipsReginfoInputSection : public InputSectionBase<ELFT> {
- typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
public:
- MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
-
- uint32_t getGeneralMask() const;
- uint32_t getGp0() const;
-
+ MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
static bool classof(const InputSectionBase<ELFT> *S);
+
+ const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo;
};
} // namespace elf2
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index 883b623f9e2c..a6df9ed48cdc 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -312,7 +312,7 @@ static bool isUnderSysroot(StringRef Path) {
}
// Entry point. The other functions or classes are private to this file.
-void lld::elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
+void elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
StringRef Path = MB.getBufferIdentifier();
LinkerScript(A, MB.getBuffer(), isUnderSysroot(Path)).run();
}
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp
index b719b1a09c25..f682f3b8b473 100644
--- a/ELF/MarkLive.cpp
+++ b/ELF/MarkLive.cpp
@@ -79,7 +79,7 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
// This is the main function of the garbage collector.
// Starting from GC-root sections, this function visits all reachable
// sections to set their "Live" bits.
-template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
+template <class ELFT> void elf2::markLive(SymbolTable<ELFT> *Symtab) {
SmallVector<InputSection<ELFT> *, 256> Q;
auto Enqueue = [&](InputSectionBase<ELFT> *Sec) {
@@ -116,16 +116,15 @@ template <class ELFT> void lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
// Preserve special sections.
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles())
for (InputSectionBase<ELFT> *Sec : F->getSections())
- if (Sec && Sec != &InputSection<ELFT>::Discarded)
- if (isReserved(Sec))
- Enqueue(Sec);
+ if (Sec && Sec != &InputSection<ELFT>::Discarded && isReserved(Sec))
+ Enqueue(Sec);
// Mark all reachable sections.
while (!Q.empty())
forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue);
}
-template void lld::elf2::markLive<ELF32LE>(SymbolTable<ELF32LE> *);
-template void lld::elf2::markLive<ELF32BE>(SymbolTable<ELF32BE> *);
-template void lld::elf2::markLive<ELF64LE>(SymbolTable<ELF64LE> *);
-template void lld::elf2::markLive<ELF64BE>(SymbolTable<ELF64BE> *);
+template void elf2::markLive<ELF32LE>(SymbolTable<ELF32LE> *);
+template void elf2::markLive<ELF32BE>(SymbolTable<ELF32BE> *);
+template void elf2::markLive<ELF64LE>(SymbolTable<ELF64LE> *);
+template void elf2::markLive<ELF64BE>(SymbolTable<ELF64BE> *);
diff --git a/ELF/Options.td b/ELF/Options.td
index 622cbb93bf11..1b02c5c8b795 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -109,6 +109,9 @@ def verbose : Flag<["--"], "verbose">;
def whole_archive : Flag<["--", "-"], "whole-archive">,
HelpText<"Force load of all members in a static library">;
+def wrap : Separate<["--", "-"], "wrap">, MetaVarName<"<symbol>">,
+ HelpText<"Use wrapper functions for symbol">;
+
def z : JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
HelpText<"Linker option extensions">;
@@ -136,6 +139,7 @@ def alias_soname_soname : Separate<["-"], "soname">, Alias<soname>;
def alias_script_T : Separate<["-"], "T">, Alias<script>;
def alias_strip_all: Flag<["-"], "s">, Alias<strip_all>;
def alias_undefined_u : Separate<["-"], "u">, Alias<undefined>;
+def alias_wrap_wrap : Joined<["--", "-"], "wrap=">, Alias<wrap>;
// Our symbol resolution algorithm handles symbols in archive files differently
// than traditional linkers, so we don't need --start-group and --end-group.
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 30ec83f4d3b1..2aa814524d6b 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -21,21 +21,20 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
-bool lld::elf2::HasGotOffRel = false;
+bool elf2::HasGotOffRel = false;
template <class ELFT>
-OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type,
- uintX_t sh_flags)
+OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t Type,
+ uintX_t Flags)
: Name(Name) {
memset(&Header, 0, sizeof(Elf_Shdr));
- Header.sh_type = sh_type;
- Header.sh_flags = sh_flags;
+ Header.sh_type = Type;
+ Header.sh_flags = Flags;
}
template <class ELFT>
GotPltSection<ELFT>::GotPltSection()
- : OutputSectionBase<ELFT>(".got.plt", llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) {
+ : OutputSectionBase<ELFT>(".got.plt", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
this->Header.sh_addralign = sizeof(uintX_t);
}
@@ -70,10 +69,9 @@ template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
template <class ELFT>
GotSection<ELFT>::GotSection()
- : OutputSectionBase<ELFT>(".got", llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) {
+ : OutputSectionBase<ELFT>(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE) {
if (Config->EMachine == EM_MIPS)
- this->Header.sh_flags |= llvm::ELF::SHF_MIPS_GPREL;
+ this->Header.sh_flags |= SHF_MIPS_GPREL;
this->Header.sh_addralign = sizeof(uintX_t);
}
@@ -120,7 +118,7 @@ const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
template <class ELFT>
unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
- // TODO: Update when the suppoort of GOT entries for local symbols is added.
+ // TODO: Update when the support of GOT entries for local symbols is added.
return Target->getGotHeaderEntriesNum();
}
@@ -151,8 +149,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
template <class ELFT>
PltSection<ELFT>::PltSection()
- : OutputSectionBase<ELFT>(".plt", llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR) {
+ : OutputSectionBase<ELFT>(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR) {
this->Header.sh_addralign = 16;
}
@@ -199,9 +196,7 @@ template <class ELFT> void PltSection<ELFT>::finalize() {
template <class ELFT>
RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela)
- : OutputSectionBase<ELFT>(Name,
- IsRela ? llvm::ELF::SHT_RELA : llvm::ELF::SHT_REL,
- llvm::ELF::SHF_ALLOC),
+ : OutputSectionBase<ELFT>(Name, IsRela ? SHT_RELA : SHT_REL, SHF_ALLOC),
IsRela(IsRela) {
this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
@@ -328,15 +323,14 @@ template <class ELFT> void RelocationSection<ELFT>::finalize() {
template <class ELFT>
InterpSection<ELFT>::InterpSection()
- : OutputSectionBase<ELFT>(".interp", llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC) {
+ : OutputSectionBase<ELFT>(".interp", SHT_PROGBITS, SHF_ALLOC) {
this->Header.sh_size = Config->DynamicLinker.size() + 1;
this->Header.sh_addralign = 1;
}
template <class ELFT>
void OutputSectionBase<ELFT>::writeHeaderTo(Elf_Shdr *SHdr) {
- Header.sh_name = Out<ELFT>::ShStrTab->getOffset(Name);
+ Header.sh_name = Out<ELFT>::ShStrTab->addString(Name);
*SHdr = Header;
}
@@ -346,8 +340,7 @@ template <class ELFT> void InterpSection<ELFT>::writeTo(uint8_t *Buf) {
template <class ELFT>
HashTableSection<ELFT>::HashTableSection()
- : OutputSectionBase<ELFT>(".hash", llvm::ELF::SHT_HASH,
- llvm::ELF::SHF_ALLOC) {
+ : OutputSectionBase<ELFT>(".hash", SHT_HASH, SHF_ALLOC) {
this->Header.sh_entsize = sizeof(Elf_Word);
this->Header.sh_addralign = sizeof(Elf_Word);
}
@@ -404,8 +397,7 @@ static uint32_t hashGnu(StringRef Name) {
template <class ELFT>
GnuHashTableSection<ELFT>::GnuHashTableSection()
- : OutputSectionBase<ELFT>(".gnu.hash", llvm::ELF::SHT_GNU_HASH,
- llvm::ELF::SHF_ALLOC) {
+ : OutputSectionBase<ELFT>(".gnu.hash", SHT_GNU_HASH, SHF_ALLOC) {
this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4;
this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
}
@@ -545,8 +537,7 @@ void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolBody *> &Symbols) {
template <class ELFT>
DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
- : OutputSectionBase<ELFT>(".dynamic", llvm::ELF::SHT_DYNAMIC,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE),
+ : OutputSectionBase<ELFT>(".dynamic", SHT_DYNAMIC, SHF_ALLOC | SHF_WRITE),
SymTab(SymTab) {
Elf_Shdr &Header = this->Header;
Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
@@ -556,7 +547,7 @@ DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
// See "Special Section" in Chapter 4 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
if (Config->EMachine == EM_MIPS)
- Header.sh_flags = llvm::ELF::SHF_ALLOC;
+ Header.sh_flags = SHF_ALLOC;
}
template <class ELFT> void DynamicSection<ELFT>::finalize() {
@@ -590,12 +581,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
if (!Config->RPath.empty()) {
++NumEntries; // DT_RUNPATH / DT_RPATH
- Out<ELFT>::DynStrTab->add(Config->RPath);
+ Out<ELFT>::DynStrTab->reserve(Config->RPath);
}
if (!Config->SoName.empty()) {
++NumEntries; // DT_SONAME
- Out<ELFT>::DynStrTab->add(Config->SoName);
+ Out<ELFT>::DynStrTab->reserve(Config->SoName);
}
if (PreInitArraySec)
@@ -608,7 +599,7 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
if (!F->isNeeded())
continue;
- Out<ELFT>::DynStrTab->add(F->getSoName());
+ Out<ELFT>::DynStrTab->reserve(F->getSoName());
++NumEntries;
}
@@ -696,7 +687,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA());
WritePtr(DT_SYMENT, sizeof(Elf_Sym));
WritePtr(DT_STRTAB, Out<ELFT>::DynStrTab->getVA());
- WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->data().size());
+ WriteVal(DT_STRSZ, Out<ELFT>::DynStrTab->getSize());
if (Out<ELFT>::GnuHashTab)
WritePtr(DT_GNU_HASH, Out<ELFT>::GnuHashTab->getVA());
if (Out<ELFT>::HashTab)
@@ -712,10 +703,10 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
// DT_RPATH is used for indirect dependencies as well.
if (!Config->RPath.empty())
WriteVal(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
- Out<ELFT>::DynStrTab->getOffset(Config->RPath));
+ Out<ELFT>::DynStrTab->addString(Config->RPath));
if (!Config->SoName.empty())
- WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->getOffset(Config->SoName));
+ WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->addString(Config->SoName));
auto WriteArray = [&](int32_t T1, int32_t T2,
const OutputSectionBase<ELFT> *Sec) {
@@ -730,7 +721,7 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
if (F->isNeeded())
- WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getOffset(F->getSoName()));
+ WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName()));
if (InitSym)
WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));
@@ -765,9 +756,9 @@ template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
}
template <class ELFT>
-OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t sh_type,
- uintX_t sh_flags)
- : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
+OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t Type,
+ uintX_t Flags)
+ : OutputSectionBase<ELFT>(Name, Type, Flags) {}
template <class ELFT>
void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
@@ -779,14 +770,14 @@ void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
this->Header.sh_addralign = Align;
uintX_t Off = this->Header.sh_size;
- Off = RoundUpToAlignment(Off, Align);
+ Off = align(Off, Align);
S->OutSecOff = Off;
Off += S->getSize();
this->Header.sh_size = Off;
}
template <class ELFT>
-typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
+typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) {
switch (S.kind()) {
case SymbolBody::DefinedSyntheticKind: {
auto &D = cast<DefinedSynthetic<ELFT>>(S);
@@ -797,6 +788,11 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
InputSectionBase<ELFT> *SC = DR.Section;
if (!SC)
return DR.Sym.st_value;
+
+ // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
+ // from the beginning of the section.
+ if (Config->EMachine == EM_AMDGPU)
+ return SC->getOffset(DR.Sym);
if (DR.Sym.getType() == STT_TLS)
return SC->OutSec->getVA() + SC->getOffset(DR.Sym) -
Out<ELFT>::TlsPhdr->p_vaddr;
@@ -824,9 +820,9 @@ typename ELFFile<ELFT>::uintX_t lld::elf2::getSymVA(const SymbolBody &S) {
// For non-local symbols, use getSymVA instead.
template <class ELFT, bool IsRela>
typename ELFFile<ELFT>::uintX_t
-lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
- const Elf_Rel_Impl<ELFT, IsRela> &RI,
- typename ELFFile<ELFT>::uintX_t Addend) {
+elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
+ const Elf_Rel_Impl<ELFT, IsRela> &RI,
+ typename ELFFile<ELFT>::uintX_t Addend) {
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
@@ -868,7 +864,7 @@ lld::elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
// Returns true if a symbol can be replaced at load-time by a symbol
// with the same name defined in other ELF executable or DSO.
-bool lld::elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
+bool elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
if (!Body)
return false; // Body is a local symbol.
if (Body->isShared())
@@ -910,9 +906,9 @@ template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
}
template <class ELFT>
-EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t sh_type,
- uintX_t sh_flags)
- : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
+EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t Type,
+ uintX_t Flags)
+ : OutputSectionBase<ELFT>(Name, Type, Flags) {}
template <class ELFT>
EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
@@ -980,7 +976,7 @@ void EHOutputSection<ELFT>::addSectionAux(
auto P = CieMap.insert(std::make_pair(CieInfo, Cies.size()));
if (P.second) {
Cies.push_back(C);
- this->Header.sh_size += RoundUpToAlignment(Length, sizeof(uintX_t));
+ this->Header.sh_size += align(Length, sizeof(uintX_t));
}
OffsetToIndex[Offset] = P.first->second;
} else {
@@ -993,7 +989,7 @@ void EHOutputSection<ELFT>::addSectionAux(
if (I == OffsetToIndex.end())
error("Invalid CIE reference");
Cies[I->second].Fdes.push_back(EHRegion<ELFT>(S, Index));
- this->Header.sh_size += RoundUpToAlignment(Length, sizeof(uintX_t));
+ this->Header.sh_size += align(Length, sizeof(uintX_t));
}
}
@@ -1046,7 +1042,7 @@ static typename ELFFile<ELFT>::uintX_t writeAlignedCieOrFde(StringRef Data,
uint8_t *Buf) {
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
const endianness E = ELFT::TargetEndianness;
- uint64_t Len = RoundUpToAlignment(Data.size(), sizeof(uintX_t));
+ uint64_t Len = align(Data.size(), sizeof(uintX_t));
write32<E>(Buf, Len - 4);
memcpy(Buf + 4, Data.data() + 4, Data.size() - 4);
return Len;
@@ -1083,9 +1079,9 @@ template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) {
}
template <class ELFT>
-MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t sh_type,
- uintX_t sh_flags)
- : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
+MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t Type,
+ uintX_t Flags)
+ : OutputSectionBase<ELFT>(Name, Type, Flags) {}
template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
if (shouldTailMerge()) {
@@ -1165,21 +1161,50 @@ template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
template <class ELFT>
StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
- : OutputSectionBase<ELFT>(Name, llvm::ELF::SHT_STRTAB,
- Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
+ : OutputSectionBase<ELFT>(Name, SHT_STRTAB,
+ Dynamic ? (uintX_t)SHF_ALLOC : 0),
Dynamic(Dynamic) {
this->Header.sh_addralign = 1;
}
+// String tables are created in two phases. First you call reserve()
+// to reserve room in the string table, and then call addString() to actually
+// add that string.
+//
+// Why two phases? We want to know the size of the string table as early as
+// possible to fix file layout. So we have separated finalize(), which
+// determines the size of the section, from writeTo(), which writes the section
+// contents to the output buffer. If we merge reserve() with addString(),
+// we need a plumbing work for finalize() and writeTo() so that offsets
+// we obtained in the former function can be written in the latter.
+// This design eliminated that need.
+template <class ELFT> void StringTableSection<ELFT>::reserve(StringRef S) {
+ Reserved += S.size() + 1; // +1 for NUL
+}
+
+// Adds a string to the string table. You must call reserve() with the
+// same string before calling addString().
+template <class ELFT> size_t StringTableSection<ELFT>::addString(StringRef S) {
+ size_t Pos = Used;
+ Strings.push_back(S);
+ Used += S.size() + 1;
+ Reserved -= S.size() + 1;
+ assert((int64_t)Reserved >= 0);
+ return Pos;
+}
+
template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
- StringRef Data = StrTabBuilder.data();
- memcpy(Buf, Data.data(), Data.size());
+ // ELF string tables start with NUL byte, so advance the pointer by one.
+ ++Buf;
+ for (StringRef S : Strings) {
+ memcpy(Buf, S.data(), S.size());
+ Buf += S.size() + 1;
+ }
}
template <class ELFT>
-bool lld::elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File,
- StringRef SymName,
- const typename ELFFile<ELFT>::Elf_Sym &Sym) {
+bool elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File, StringRef SymName,
+ const typename ELFFile<ELFT>::Elf_Sym &Sym) {
if (Sym.getType() == STT_SECTION)
return false;
@@ -1208,16 +1233,12 @@ bool lld::elf2::shouldKeepInSymtab(const ObjectFile<ELFT> &File,
template <class ELFT>
SymbolTableSection<ELFT>::SymbolTableSection(
SymbolTable<ELFT> &Table, StringTableSection<ELFT> &StrTabSec)
- : OutputSectionBase<ELFT>(
- StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
- StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB,
- StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
+ : OutputSectionBase<ELFT>(StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
+ StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
+ StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
Table(Table), StrTabSec(StrTabSec) {
- typedef OutputSectionBase<ELFT> Base;
- typename Base::Elf_Shdr &Header = this->Header;
-
- Header.sh_entsize = sizeof(Elf_Sym);
- Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+ this->Header.sh_entsize = sizeof(Elf_Sym);
+ this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
}
// Orders symbols according to their positions in the GOT,
@@ -1259,14 +1280,14 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
template <class ELFT>
void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) {
- StrTabSec.add(Name);
+ StrTabSec.reserve(Name);
++NumVisible;
++NumLocals;
}
template <class ELFT>
void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) {
- StrTabSec.add(Body->getName());
+ StrTabSec.reserve(Body->getName());
Symbols.push_back(Body);
++NumVisible;
}
@@ -1306,9 +1327,13 @@ void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
continue;
const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
ESym->st_shndx = OutSec->SectionIndex;
- VA += OutSec->getVA() + Section->getOffset(Sym);
+ VA = Section->getOffset(Sym);
+ // Symbol offsets for AMDGPU need to be the offset in bytes of the
+ // symbol from the beginning of the section.
+ if (Config->EMachine != EM_AMDGPU)
+ VA += OutSec->getVA();
}
- ESym->st_name = StrTabSec.getOffset(SymName);
+ ESym->st_name = StrTabSec.addString(SymName);
ESym->st_size = Sym.st_size;
ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
ESym->st_value = VA;
@@ -1363,7 +1388,7 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
}
StringRef Name = Body->getName();
- ESym->st_name = StrTabSec.getOffset(Name);
+ ESym->st_name = StrTabSec.addString(Name);
unsigned char Type = STT_NOTYPE;
uintX_t Size = 0;
@@ -1413,13 +1438,14 @@ template <class ELFT>
void MipsReginfoOutputSection<ELFT>::writeTo(uint8_t *Buf) {
auto *R = reinterpret_cast<Elf_Mips_RegInfo *>(Buf);
R->ri_gp_value = getMipsGpAddr<ELFT>();
- R->ri_gprmask = GeneralMask;
+ R->ri_gprmask = GprMask;
}
template <class ELFT>
void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ // Copy input object file's .reginfo gprmask to output.
auto *S = cast<MipsReginfoInputSection<ELFT>>(C);
- GeneralMask |= S->getGeneralMask();
+ GprMask |= S->Reginfo->ri_gprmask;
}
namespace lld {
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index 6dca2b570308..d7109c580cdc 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -329,21 +329,18 @@ class StringTableSection final : public OutputSectionBase<ELFT> {
public:
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
StringTableSection(StringRef Name, bool Dynamic);
- void add(StringRef S) { StrTabBuilder.add(S); }
- size_t getOffset(StringRef S) const { return StrTabBuilder.getOffset(S); }
- StringRef data() const { return StrTabBuilder.data(); }
+ void reserve(StringRef S);
+ size_t addString(StringRef S);
void writeTo(uint8_t *Buf) override;
-
- void finalize() override {
- StrTabBuilder.finalize();
- this->Header.sh_size = StrTabBuilder.data().size();
- }
-
+ size_t getSize() const { return Used + Reserved; }
+ void finalize() override { this->Header.sh_size = getSize(); }
bool isDynamic() const { return Dynamic; }
private:
const bool Dynamic;
- llvm::StringTableBuilder StrTabBuilder{llvm::StringTableBuilder::ELF};
+ std::vector<StringRef> Strings;
+ size_t Used = 1; // ELF string tables start with a NUL byte, so 1.
+ size_t Reserved = 0;
};
template <class ELFT>
@@ -429,9 +426,13 @@ public:
void addSection(InputSectionBase<ELFT> *S) override;
private:
- uint32_t GeneralMask = 0;
+ uint32_t GprMask = 0;
};
+inline uint64_t align(uint64_t Value, uint64_t Align) {
+ return llvm::RoundUpToAlignment(Value, Align);
+}
+
// All output sections that are hadnled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 74951bad410f..65f5dff9d7a3 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -18,6 +18,7 @@
#include "Config.h"
#include "Error.h"
#include "Symbols.h"
+#include "llvm/Support/StringSaver.h"
using namespace llvm;
using namespace llvm::object;
@@ -26,8 +27,6 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
-template <class ELFT> SymbolTable<ELFT>::SymbolTable() {}
-
// All input object files must be for the same architecture
// (e.g. it does not make sense to link x86 object files with
// MIPS object files.) This function checks for that error.
@@ -64,7 +63,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
// DSOs are uniquified not by filename but by soname.
F->parseSoName();
- if (!IncludedSoNames.insert(F->getSoName()).second)
+ if (!SoNames.insert(F->getSoName()).second)
return;
SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
@@ -100,17 +99,20 @@ SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
}
template <class ELFT>
-void SymbolTable<ELFT>::addAbsolute(StringRef Name,
- typename ELFFile<ELFT>::Elf_Sym &ESym) {
- resolve(new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr));
+SymbolBody *SymbolTable<ELFT>::addAbsolute(StringRef Name, Elf_Sym &ESym) {
+ // Pass nullptr because absolute symbols have no corresponding input sections.
+ auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr);
+ resolve(Sym);
+ return Sym;
}
template <class ELFT>
-void SymbolTable<ELFT>::addSynthetic(StringRef Name,
- OutputSectionBase<ELFT> &Section,
- typename ELFFile<ELFT>::uintX_t Value) {
+SymbolBody *SymbolTable<ELFT>::addSynthetic(StringRef Name,
+ OutputSectionBase<ELFT> &Section,
+ uintX_t Value) {
auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Value, Section);
resolve(Sym);
+ return Sym;
}
// Add Name as an "ignored" symbol. An ignored symbol is a regular
@@ -118,10 +120,27 @@ void SymbolTable<ELFT>::addSynthetic(StringRef Name,
// file's symbol table. Such symbols are useful for some linker-defined symbols.
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
- auto *Sym = new (Alloc)
- DefinedRegular<ELFT>(Name, ElfSym<ELFT>::IgnoreUndef, nullptr);
- resolve(Sym);
- return Sym;
+ return addAbsolute(Name, ElfSym<ELFT>::IgnoredWeak);
+}
+
+// The 'strong' variant of the addIgnored. Adds symbol which has a global
+// binding and cannot be substituted.
+template <class ELFT>
+SymbolBody *SymbolTable<ELFT>::addIgnoredStrong(StringRef Name) {
+ return addAbsolute(Name, ElfSym<ELFT>::Ignored);
+}
+
+// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
+// Used to implement --wrap.
+template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
+ if (Symtab.count(Name) == 0)
+ return;
+ StringSaver Saver(Alloc);
+ Symbol *Sym = addUndefined(Name)->getSymbol();
+ Symbol *Real = addUndefined(Saver.save("__real_" + Name))->getSymbol();
+ Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->getSymbol();
+ Real->Body = Sym->Body;
+ Sym->Body = Wrap->Body;
}
// Returns a file from which symbol B was created.
@@ -136,6 +155,8 @@ ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) {
return nullptr;
}
+// Construct a string in the form of "Sym in File1 and File2".
+// Used to construct an error message.
template <class ELFT>
std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
ELFFileBase<ELFT> *OldFile = findFile(Old);
@@ -184,8 +205,8 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
Sym->Body = New;
}
+// Find an existing symbol or create and insert a new one.
template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
- // Find an existing Symbol or create and insert a new one.
StringRef Name = New->getName();
Symbol *&Sym = Symtab[Name];
if (!Sym)
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
index 4f8f5afa420a..16ed821bf01a 100644
--- a/ELF/SymbolTable.h
+++ b/ELF/SymbolTable.h
@@ -31,9 +31,10 @@ class Undefined;
// undefined, it'll read an archive member to read a real definition
// to replace the lazy symbol. The logic is implemented in resolve().
template <class ELFT> class SymbolTable {
-public:
- SymbolTable();
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+public:
void addFile(std::unique_ptr<InputFile> File);
const llvm::MapVector<StringRef, Symbol *> &getSymbols() const {
@@ -50,13 +51,15 @@ public:
SymbolBody *addUndefined(StringRef Name);
SymbolBody *addUndefinedOpt(StringRef Name);
- void addAbsolute(StringRef Name,
- typename llvm::object::ELFFile<ELFT>::Elf_Sym &ESym);
- void addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
- typename llvm::object::ELFFile<ELFT>::uintX_t Value);
+ SymbolBody *addAbsolute(StringRef Name, Elf_Sym &ESym);
+ SymbolBody *addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
+ uintX_t Value);
SymbolBody *addIgnored(StringRef Name);
+ SymbolBody *addIgnoredStrong(StringRef Name);
+
void scanShlibUndefined();
SymbolBody *find(StringRef Name);
+ void wrap(StringRef Name);
ELFFileBase<ELFT> *findFile(SymbolBody *B);
private:
@@ -66,8 +69,6 @@ private:
void resolve(SymbolBody *Body);
std::string conflictMsg(SymbolBody *Old, SymbolBody *New);
- std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
-
// The order the global symbols are in is not defined. We can use an arbitrary
// order, but it has to be reproducible. That is true even when cross linking.
// The default hashing of StringRef produces different results on 32 and 64
@@ -78,13 +79,18 @@ private:
llvm::MapVector<StringRef, Symbol *> Symtab;
llvm::BumpPtrAllocator Alloc;
+ // Comdat groups define "link once" sections. If two comdat groups have the
+ // same name, only one of them is linked, and the other is ignored. This set
+ // is used to uniquify them.
llvm::DenseSet<StringRef> ComdatGroups;
- // The writer needs to infer the machine type from the object files.
+ // The symbol table owns all file objects.
+ std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
-
std::vector<std::unique_ptr<SharedFile<ELFT>>> SharedFiles;
- llvm::DenseSet<StringRef> IncludedSoNames;
+
+ // Set of .so files to not link the same shared object file more than once.
+ llvm::DenseSet<StringRef> SoNames;
};
} // namespace elf2
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 4af1b88e79ad..3c864cbe2b67 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -120,11 +120,13 @@ std::unique_ptr<InputFile> Lazy::getMember() {
template <class ELFT> static void doInitSymbols() {
ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
- ElfSym<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
- ElfSym<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
+ ElfSym<ELFT>::IgnoredWeak.setBinding(STB_WEAK);
+ ElfSym<ELFT>::IgnoredWeak.setVisibility(STV_HIDDEN);
+ ElfSym<ELFT>::Ignored.setBinding(STB_GLOBAL);
+ ElfSym<ELFT>::Ignored.setVisibility(STV_HIDDEN);
}
-void lld::elf2::initSymbols() {
+void elf2::initSymbols() {
doInitSymbols<ELF32LE>();
doInitSymbols<ELF32BE>();
doInitSymbols<ELF64LE>();
@@ -136,12 +138,12 @@ template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
-template class lld::elf2::UndefinedElf<ELF32LE>;
-template class lld::elf2::UndefinedElf<ELF32BE>;
-template class lld::elf2::UndefinedElf<ELF64LE>;
-template class lld::elf2::UndefinedElf<ELF64BE>;
+template class elf2::UndefinedElf<ELF32LE>;
+template class elf2::UndefinedElf<ELF32BE>;
+template class elf2::UndefinedElf<ELF64LE>;
+template class elf2::UndefinedElf<ELF64BE>;
-template class lld::elf2::DefinedSynthetic<ELF32LE>;
-template class lld::elf2::DefinedSynthetic<ELF32BE>;
-template class lld::elf2::DefinedSynthetic<ELF64LE>;
-template class lld::elf2::DefinedSynthetic<ELF64BE>;
+template class elf2::DefinedSynthetic<ELF32LE>;
+template class elf2::DefinedSynthetic<ELF32BE>;
+template class elf2::DefinedSynthetic<ELF64LE>;
+template class elf2::DefinedSynthetic<ELF64BE>;
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index 16a3b338b3cd..6f65ea1a72e4 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -105,6 +105,7 @@ public:
// you can access P->Backref->Body to get the resolver's result.
void setBackref(Symbol *P) { Backref = P; }
SymbolBody *repl() { return Backref ? Backref->Body : this; }
+ Symbol *getSymbol() { return Backref; }
// Decides which symbol should "win" in the symbol table, this or
// the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
@@ -299,8 +300,11 @@ template <class ELFT> struct ElfSym {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
// Used to represent an undefined symbol which we don't want
- // to add to the output file's symbol table.
- static Elf_Sym IgnoreUndef;
+ // to add to the output file's symbol table. The `IgnoredWeak`
+ // has weak binding and can be substituted. The `Ignore` has
+ // global binding and gets priority over symbols from shared libs.
+ static Elf_Sym IgnoredWeak;
+ static Elf_Sym Ignored;
// The content for _end and end symbols.
static Elf_Sym End;
@@ -314,7 +318,8 @@ template <class ELFT> struct ElfSym {
static Elf_Sym RelaIpltEnd;
};
-template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoreUndef;
+template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoredWeak;
+template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::Ignored;
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::End;
template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::MipsGp;
template <class ELFT>
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index 8d54c93570fa..6d42dbe86e54 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -122,7 +122,6 @@ private:
class X86_64TargetInfo final : public TargetInfo {
public:
X86_64TargetInfo();
- unsigned getPltRefReloc(unsigned Type) const override;
bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
void writeGotPltHeaderEntries(uint8_t *Buf) const override;
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
@@ -139,7 +138,7 @@ public:
uint8_t *PairedLoc = nullptr) const override;
bool isRelRelative(uint32_t Type) const override;
bool isTlsOptimized(unsigned Type, const SymbolBody *S) const override;
- bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const override;
+ bool isSizeReloc(uint32_t Type) const override;
unsigned relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
uint64_t P, uint64_t SA,
const SymbolBody &S) const override;
@@ -155,6 +154,23 @@ private:
uint64_t SA) const;
};
+class PPCTargetInfo final : public TargetInfo {
+public:
+ PPCTargetInfo();
+ void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
+ void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const override;
+ void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
+ void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
+ uint64_t SA, uint64_t ZA = 0,
+ uint8_t *PairedLoc = nullptr) const override;
+ bool isRelRelative(uint32_t Type) const override;
+};
+
class PPC64TargetInfo final : public TargetInfo {
public:
PPC64TargetInfo();
@@ -176,13 +192,14 @@ class AArch64TargetInfo final : public TargetInfo {
public:
AArch64TargetInfo();
unsigned getDynReloc(unsigned Type) const override;
- unsigned getPltRefReloc(unsigned Type) const override;
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const override;
+ unsigned getTlsGotReloc(unsigned Type = -1) const override;
+ bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
@@ -191,6 +208,22 @@ public:
uint8_t *PairedLoc = nullptr) const override;
};
+class AMDGPUTargetInfo final : public TargetInfo {
+public:
+ AMDGPUTargetInfo();
+ void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
+ void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const override;
+ void writePltEntry(uint8_t *Buf, uint64_t GotAddr, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const override;
+ bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
+ bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
+ void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
+ uint64_t SA, uint64_t ZA = 0,
+ uint8_t *PairedLoc = nullptr) const override;
+};
+
template <class ELFT> class MipsTargetInfo final : public TargetInfo {
public:
MipsTargetInfo();
@@ -216,6 +249,8 @@ TargetInfo *createTarget() {
return new X86TargetInfo();
case EM_AARCH64:
return new AArch64TargetInfo();
+ case EM_AMDGPU:
+ return new AMDGPUTargetInfo();
case EM_MIPS:
switch (Config->EKind) {
case ELF32LEKind:
@@ -225,6 +260,8 @@ TargetInfo *createTarget() {
default:
error("Unsupported MIPS target");
}
+ case EM_PPC:
+ return new PPCTargetInfo();
case EM_PPC64:
return new PPC64TargetInfo();
case EM_X86_64:
@@ -247,13 +284,9 @@ bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
-unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; }
-
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
-bool TargetInfo::isSizeDynReloc(uint32_t Type, const SymbolBody &S) const {
- return false;
-}
+bool TargetInfo::isSizeReloc(uint32_t Type) const { return false; }
unsigned TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
uint32_t Type, uint64_t P, uint64_t SA,
@@ -639,12 +672,6 @@ bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
}
-unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const {
- if (Type == R_X86_64_PLT32)
- return R_X86_64_PC32;
- return Type;
-}
-
bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
if (needsCopyRel(Type, S))
return false;
@@ -698,16 +725,12 @@ bool X86_64TargetInfo::isRelRelative(uint32_t Type) const {
case R_X86_64_PC32:
case R_X86_64_PC64:
case R_X86_64_PLT32:
- case R_X86_64_SIZE32:
- case R_X86_64_SIZE64:
return true;
}
}
-bool X86_64TargetInfo::isSizeDynReloc(uint32_t Type,
- const SymbolBody &S) const {
- return (Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64) &&
- canBePreempted(&S, false);
+bool X86_64TargetInfo::isSizeReloc(uint32_t Type) const {
+ return Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64;
}
bool X86_64TargetInfo::isTlsOptimized(unsigned Type,
@@ -909,6 +932,37 @@ static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; }
static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
+PPCTargetInfo::PPCTargetInfo() {}
+void PPCTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
+void PPCTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const {}
+void PPCTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
+ uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {}
+bool PPCTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+bool PPCTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+bool PPCTargetInfo::isRelRelative(uint32_t Type) const { return false; }
+
+void PPCTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+ uint64_t P, uint64_t SA, uint64_t ZA,
+ uint8_t *PairedLoc) const {
+ switch (Type) {
+ case R_PPC_ADDR16_HA:
+ write16be(Loc, applyPPCHa(SA));
+ break;
+ case R_PPC_ADDR16_LO:
+ write16be(Loc, applyPPCLo(SA));
+ break;
+ default:
+ error("unrecognized reloc " + Twine(Type));
+ }
+}
+
PPC64TargetInfo::PPC64TargetInfo() {
PCRelReloc = R_PPC64_REL24;
GotReloc = R_PPC64_GLOB_DAT;
@@ -1124,8 +1178,10 @@ void PPC64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
AArch64TargetInfo::AArch64TargetInfo() {
CopyReloc = R_AARCH64_COPY;
+ IRelativeReloc = R_AARCH64_IRELATIVE;
GotReloc = R_AARCH64_GLOB_DAT;
PltReloc = R_AARCH64_JUMP_SLOT;
+ TlsGotReloc = R_AARCH64_TLS_TPREL64;
LazyRelocations = true;
PltEntrySize = 16;
PltZeroEntrySize = 32;
@@ -1139,8 +1195,6 @@ unsigned AArch64TargetInfo::getDynReloc(unsigned Type) const {
"recompile with -fPIC.");
}
-unsigned AArch64TargetInfo::getPltRefReloc(unsigned Type) const { return Type; }
-
void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
write64le(Buf, Out<ELF64LE>::Plt->getVA());
}
@@ -1187,6 +1241,19 @@ void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
GotEntryAddr);
}
+unsigned AArch64TargetInfo::getTlsGotReloc(unsigned Type) const {
+ if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
+ Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
+ return Type;
+ return TlsGotReloc;
+}
+
+bool AArch64TargetInfo::isTlsDynReloc(unsigned Type,
+ const SymbolBody &S) const {
+ return Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
+ Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
+}
+
bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
if (Config->Shared)
return false;
@@ -1210,17 +1277,28 @@ bool AArch64TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
const SymbolBody &S) const {
- return Type == R_AARCH64_ADR_GOT_PAGE || Type == R_AARCH64_LD64_GOT_LO12_NC ||
- relocNeedsPlt(Type, S);
+ switch (Type) {
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+ case R_AARCH64_ADR_GOT_PAGE:
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ return true;
+ default:
+ return relocNeedsPlt(Type, S);
+ }
}
bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
const SymbolBody &S) const {
+ if (isGnuIFunc<ELF64LE>(S))
+ return true;
switch (Type) {
default:
return false;
case R_AARCH64_CALL26:
+ case R_AARCH64_CONDBR19:
case R_AARCH64_JUMP26:
+ case R_AARCH64_TSTBR14:
return canBePreempted(&S, true);
}
}
@@ -1273,7 +1351,8 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
updateAArch64Adr(Loc, X & 0x1FFFFF);
break;
}
- case R_AARCH64_ADR_PREL_PG_HI21: {
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: {
uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
checkInt<33>(X, Type);
updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
@@ -1286,7 +1365,14 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
or32le(Loc, (X & 0x0FFFFFFC) >> 2);
break;
}
+ case R_AARCH64_CONDBR19: {
+ uint64_t X = SA - P;
+ checkInt<21>(X, Type);
+ or32le(Loc, (X & 0x1FFFFC) << 3);
+ break;
+ }
case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
checkAlignment<8>(SA, Type);
or32le(Loc, (SA & 0xFF8) << 7);
break;
@@ -1310,11 +1396,53 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
case R_AARCH64_PREL64:
write64le(Loc, SA - P);
break;
+ case R_AARCH64_TSTBR14: {
+ uint64_t X = SA - P;
+ checkInt<16>(X, Type);
+ or32le(Loc, (X & 0xFFFC) << 3);
+ break;
+ }
default:
error("unrecognized reloc " + Twine(Type));
}
}
+AMDGPUTargetInfo::AMDGPUTargetInfo() {}
+
+void AMDGPUTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
+ llvm_unreachable("not implemented");
+}
+
+void AMDGPUTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const {
+ llvm_unreachable("not implemented");
+}
+
+void AMDGPUTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
+ uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr, int32_t Index,
+ unsigned RelOff) const {
+ llvm_unreachable("not implemented");
+}
+
+bool AMDGPUTargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+
+bool AMDGPUTargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+
+// Implementing relocations for AMDGPU is low priority since most
+// programs don't use relocations now. Thus, this function is not
+// actually called (relocateOne is called for each relocation).
+// That's why the AMDGPU port works without implementing this function.
+void AMDGPUTargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
+ uint64_t P, uint64_t SA, uint64_t ZA,
+ uint8_t *PairedLoc) const {
+ llvm_unreachable("not implemented");
+}
+
template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
PageSize = 65536;
GotHeaderEntriesNum = 2;
diff --git a/ELF/Target.h b/ELF/Target.h
index 52c2697dc60d..e9c5f4b31ae4 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -45,7 +45,6 @@ public:
virtual bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
return false;
}
- virtual unsigned getPltRefReloc(unsigned Type) const;
virtual unsigned getTlsGotReloc(unsigned Type = -1) const {
return TlsGotReloc;
}
@@ -57,8 +56,15 @@ public:
virtual void writePltEntry(uint8_t *Buf, uint64_t GotAddr,
uint64_t GotEntryAddr, uint64_t PltEntryAddr,
int32_t Index, unsigned RelOff) const = 0;
+
+ // Returns true if a relocation is relative to the place being relocated,
+ // such as relocations used for PC-relative instructions. Such relocations
+ // need not be fixed up if an image is loaded to a different address than
+ // the link-time address. So we don't have to emit a relocation for the
+ // dynamic linker if isRelRelative returns true.
virtual bool isRelRelative(uint32_t Type) const;
- virtual bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const;
+
+ virtual bool isSizeReloc(uint32_t Type) const;
virtual bool relocNeedsDynRelative(unsigned Type) const { return false; }
virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 2437a435657c..fbecfc601ac1 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -98,12 +98,9 @@ private:
};
} // anonymous namespace
-template <class ELFT> static bool shouldUseRela() {
- ELFKind K = cast<ELFFileBase<ELFT>>(Config->FirstElf)->getELFKind();
- return K == ELF64LEKind || K == ELF64BEKind;
-}
+template <class ELFT> static bool shouldUseRela() { return ELFT::Is64Bits; }
-template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
+template <class ELFT> void elf2::writeResult(SymbolTable<ELFT> *Symtab) {
// Initialize output sections that are handled by Writer specially.
// Don't reorder because the order of initialization matters.
InterpSection<ELFT> Interp;
@@ -290,18 +287,31 @@ void Writer<ELFT>::scanRelocs(
continue;
}
- if (Config->EMachine == EM_MIPS && NeedsGot) {
- // MIPS ABI has special rules to process GOT entries
- // and doesn't require relocation entries for them.
- // See "Global Offset Table" in Chapter 5 in the following document
- // for detailed description:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- Body->setUsedInDynamicReloc();
- continue;
+ if (Config->EMachine == EM_MIPS) {
+ if (NeedsGot) {
+ // MIPS ABI has special rules to process GOT entries
+ // and doesn't require relocation entries for them.
+ // See "Global Offset Table" in Chapter 5 in the following document
+ // for detailed description:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ Body->setUsedInDynamicReloc();
+ continue;
+ }
+ if (Body == Config->MipsGpDisp)
+ // MIPS _gp_disp designates offset between start of function and gp
+ // pointer into GOT therefore any relocations against it do not require
+ // dynamic relocation.
+ continue;
}
+
+ // Here we are creating a relocation for the dynamic linker based on
+ // a relocation from an object file, but some relocations need no
+ // load-time fixup. Skip such relocation.
bool CBP = canBePreempted(Body, NeedsGot);
- if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
+ bool NoDynrel = Target->isRelRelative(Type) || Target->isSizeReloc(Type);
+ if (!CBP && (NoDynrel || !Config->Shared))
continue;
+
if (CBP)
Body->setUsedInDynamicReloc();
if (NeedsPlt && Target->supportsLazyRelocations())
@@ -490,8 +500,7 @@ void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
uintX_t Off = getBss()->getSize();
for (DefinedCommon *C : Syms) {
- uintX_t Align = C->MaxAlignment;
- Off = RoundUpToAlignment(Off, Align);
+ Off = align(Off, C->MaxAlignment);
C->OffsetInBss = Off;
Off += C->Size;
}
@@ -514,7 +523,7 @@ void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) {
countTrailingZeros((uintX_t)Sym.st_value));
uintX_t Align = 1 << TrailingZeros;
Out<ELFT>::Bss->updateAlign(Align);
- Off = RoundUpToAlignment(Off, Align);
+ Off = align(Off, Align);
C->OffsetInBss = Off;
Off += Sym.st_size;
}
@@ -597,7 +606,8 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
// Don't include synthetic symbols like __init_array_start in every output.
if (auto *U = dyn_cast<DefinedRegular<ELFT>>(&B))
- if (&U->Sym == &ElfSym<ELFT>::IgnoreUndef)
+ if (&U->Sym == &ElfSym<ELFT>::IgnoredWeak ||
+ &U->Sym == &ElfSym<ELFT>::Ignored)
return false;
return true;
@@ -630,8 +640,6 @@ public:
private:
SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
StringRef OutsecName);
- OutputSectionBase<ELFT> *createAux(InputSectionBase<ELFT> *C,
- const SectionKey<ELFT::Is64Bits> &Key);
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
};
@@ -645,25 +653,22 @@ OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
OutputSectionBase<ELFT> *&Sec = Map[Key];
if (Sec)
return {Sec, false};
- Sec = createAux(C, Key);
- return {Sec, true};
-}
-template <class ELFT>
-OutputSectionBase<ELFT> *
-OutputSectionFactory<ELFT>::createAux(InputSectionBase<ELFT> *C,
- const SectionKey<ELFT::Is64Bits> &Key) {
switch (C->SectionKind) {
case InputSectionBase<ELFT>::Regular:
- return new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ break;
case InputSectionBase<ELFT>::EHFrame:
- return new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ Sec = new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ break;
case InputSectionBase<ELFT>::Merge:
- return new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ break;
case InputSectionBase<ELFT>::MipsReginfo:
- return new MipsReginfoOutputSection<ELFT>();
+ Sec = new MipsReginfoOutputSection<ELFT>();
+ break;
}
- llvm_unreachable("Unknown output section type");
+ return {Sec, true};
}
template <class ELFT>
@@ -832,7 +837,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
for (OutputSectionBase<ELFT> *Sec : OutputSections)
- Out<ELFT>::ShStrTab->add(Sec->getName());
+ Out<ELFT>::ShStrTab->reserve(Sec->getName());
// Finalizers fix each section's size.
// .dynamic section's finalizer may add strings to .dynstr,
@@ -976,6 +981,18 @@ static uint32_t toPhdrFlags(uint64_t Flags) {
return Ret;
}
+/// For AMDGPU we need to use custom segment kinds in order to specify which
+/// address space data should be loaded into.
+template <class ELFT>
+static uint32_t getAmdgpuPhdr(OutputSectionBase<ELFT> *Sec) {
+ uint32_t Flags = Sec->getFlags();
+ if (Flags & SHF_AMDGPU_HSA_CODE)
+ return PT_AMDGPU_HSA_LOAD_CODE_AGENT;
+ if ((Flags & SHF_AMDGPU_HSA_GLOBAL) && !(Flags & SHF_AMDGPU_HSA_AGENT))
+ return PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM;
+ return PT_LOAD;
+}
+
template <class ELFT>
void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
uintX_t VA) {
@@ -1024,8 +1041,8 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
if (FirstNonRelRo || PH->p_flags != Flags) {
- VA = RoundUpToAlignment(VA, Target->getPageSize());
- FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
+ VA = align(VA, Target->getPageSize());
+ FileOff = align(FileOff, Target->getPageSize());
if (FirstNonRelRo)
RelroAligned = true;
}
@@ -1033,15 +1050,17 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
if (PH->p_flags != Flags) {
// Flags changed. Create a new PT_LOAD.
PH = &Phdrs[++PhdrIdx];
- setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
+ uint32_t PTType = (Config->EMachine != EM_AMDGPU) ? (uint32_t)PT_LOAD
+ : getAmdgpuPhdr(Sec);
+ setPhdr(PH, PTType, Flags, FileOff, VA, 0, Target->getPageSize());
}
if (Sec->getFlags() & SHF_TLS) {
if (!TlsPhdr.p_vaddr)
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
if (Sec->getType() != SHT_NOBITS)
- VA = RoundUpToAlignment(VA, Sec->getAlign());
- uintX_t TVA = RoundUpToAlignment(VA + ThreadBssOffset, Sec->getAlign());
+ VA = align(VA, Sec->getAlign());
+ uintX_t TVA = align(VA + ThreadBssOffset, Sec->getAlign());
Sec->setVA(TVA);
TlsPhdr.p_memsz += Sec->getSize();
if (Sec->getType() == SHT_NOBITS) {
@@ -1052,7 +1071,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
} else {
- VA = RoundUpToAlignment(VA, Sec->getAlign());
+ VA = align(VA, Sec->getAlign());
Sec->setVA(VA);
VA += Sec->getSize();
if (InRelRo)
@@ -1060,7 +1079,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
}
- FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
+ FileOff = align(FileOff, Sec->getAlign());
Sec->setFileOffset(FileOff);
if (Sec->getType() != SHT_NOBITS)
FileOff += Sec->getSize();
@@ -1073,7 +1092,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
if (TlsPhdr.p_vaddr) {
// The TLS pointer goes after PT_TLS. At least glibc will align it,
// so round up the size to make sure the offsets are correct.
- TlsPhdr.p_memsz = RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align);
+ TlsPhdr.p_memsz = align(TlsPhdr.p_memsz, TlsPhdr.p_align);
Phdrs[++PhdrIdx] = TlsPhdr;
Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
}
@@ -1105,7 +1124,7 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() {
}
// Add space for section headers.
- SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
+ SectionHeaderOff = align(FileOff, ELFT::Is64Bits ? 8 : 4);
FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
// Update "_end" and "end" symbols so that they
@@ -1146,7 +1165,7 @@ static uint32_t getELFFlags() {
if (Config->EMachine != EM_MIPS)
return 0;
// FIXME: In fact ELF flags depends on ELF flags of input object files
- // and selected emulation. For now just use hadr coded values.
+ // and selected emulation. For now just use hard coded values.
uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2;
if (Config->Shared)
V |= EF_MIPS_PIC;
@@ -1238,8 +1257,17 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
Sec->writeTo(Buf + Sec->getFileOff());
}
+ // Write all sections but string table sections. We know the sizes of the
+ // string tables already, but they may not have actual strings yet (only
+ // room may be reserved), because writeTo() is allowed to add actual
+ // strings to the string tables.
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ if (Sec != Out<ELFT>::Opd && Sec->getType() != SHT_STRTAB)
+ Sec->writeTo(Buf + Sec->getFileOff());
+
+ // Write string table sections.
for (OutputSectionBase<ELFT> *Sec : OutputSections)
- if (Sec != Out<ELFT>::Opd)
+ if (Sec != Out<ELFT>::Opd && Sec->getType() == SHT_STRTAB)
Sec->writeTo(Buf + Sec->getFileOff());
}
@@ -1275,7 +1303,7 @@ template <class ELFT> void Writer<ELFT>::buildSectionMap() {
InputToOutputSection[Name] = OutSec.first;
}
-template void lld::elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
-template void lld::elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
-template void lld::elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
-template void lld::elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
+template void elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
+template void elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
+template void elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
+template void elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
diff --git a/lib/Config/CMakeLists.txt b/lib/Config/CMakeLists.txt
index f7ea0423b2c9..e971b0b7aa62 100644
--- a/lib/Config/CMakeLists.txt
+++ b/lib/Config/CMakeLists.txt
@@ -1,5 +1,9 @@
-add_llvm_library(lldConfig
+add_lld_library(lldConfig
Version.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLD_INCLUDE_DIR}/lld/Config
+
LINK_LIBS
LLVMSupport
)
diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt
index 009b50a38335..41e0e7661b9c 100644
--- a/lib/Core/CMakeLists.txt
+++ b/lib/Core/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldCore
+add_lld_library(lldCore
DefinedAtom.cpp
Error.cpp
File.cpp
@@ -7,6 +7,10 @@ add_llvm_library(lldCore
Resolver.cpp
SymbolTable.cpp
Writer.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLD_INCLUDE_DIR}/lld/Core
+
LINK_LIBS
LLVMSupport
)
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 64498ccf78ba..840ccce50ab3 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -8,12 +8,16 @@ set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
tablegen(LLVM DarwinLdOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(DriverOptionsTableGen)
-add_llvm_library(lldDriver
+add_lld_library(lldDriver
CoreDriver.cpp
DarwinLdDriver.cpp
Driver.cpp
GnuLdDriver.cpp
UniversalDriver.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLD_INCLUDE_DIR}/lld/Driver
+
LINK_LIBS
lldConfig
lldMachO
@@ -21,7 +25,6 @@ add_llvm_library(lldDriver
lldELF
lldELF2
lldAArch64ELFTarget
- lldAMDGPUELFTarget
lldARMELFTarget
lldHexagonELFTarget
lldMipsELFTarget
diff --git a/lib/Driver/GnuLdDriver.cpp b/lib/Driver/GnuLdDriver.cpp
index 8c75126d6d41..1cff481dd8d7 100644
--- a/lib/Driver/GnuLdDriver.cpp
+++ b/lib/Driver/GnuLdDriver.cpp
@@ -325,7 +325,6 @@ std::unique_ptr<ELFLinkingContext>
GnuLdDriver::createELFLinkingContext(llvm::Triple triple) {
std::unique_ptr<ELFLinkingContext> p;
if ((p = elf::createAArch64LinkingContext(triple))) return p;
- if ((p = elf::createAMDGPULinkingContext(triple))) return p;
if ((p = elf::createARMLinkingContext(triple))) return p;
if ((p = elf::createExampleLinkingContext(triple))) return p;
if ((p = elf::createHexagonLinkingContext(triple))) return p;
diff --git a/lib/ReaderWriter/CMakeLists.txt b/lib/ReaderWriter/CMakeLists.txt
index 588f0d85a586..2bb5655b9e35 100644
--- a/lib/ReaderWriter/CMakeLists.txt
+++ b/lib/ReaderWriter/CMakeLists.txt
@@ -6,10 +6,14 @@ if (MSVC)
add_definitions(-wd4062) # Suppress 'warning C4062: Enumerator has no associated handler in a switch statement.'
endif()
-add_llvm_library(lldReaderWriter
+add_lld_library(lldReaderWriter
CoreLinkingContext.cpp
FileArchive.cpp
LinkerScript.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLD_INCLUDE_DIR}/lld/ReaderWriter
+
LINK_LIBS
lldCore
lldYAML
diff --git a/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt b/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
index 2347dda9adb0..aae6420008a4 100644
--- a/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldAArch64ELFTarget
+add_lld_library(lldAArch64ELFTarget
AArch64LinkingContext.cpp
AArch64TargetHandler.cpp
AArch64RelocationHandler.cpp
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp
deleted file mode 100644
index 89efeb23d6f8..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AMDGPUExecutableWriter.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-AMDGPUExecutableWriter::AMDGPUExecutableWriter(AMDGPULinkingContext &ctx,
- AMDGPUTargetLayout &layout)
- : ExecutableWriter(ctx, layout), _ctx(ctx) {}
-
-void AMDGPUExecutableWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &Result) {
- // ExecutableWriter::createImplicitFiles() adds C runtime symbols that we
- // don't need, so we use the OutputELFWriter implementation instead.
- OutputELFWriter<ELF64LE>::createImplicitFiles(Result);
-}
-
-void AMDGPUExecutableWriter::finalizeDefaultAtomValues() {
-
- // ExecutableWriter::finalizeDefaultAtomValues() assumes the presence of
- // C runtime symbols. However, since we skip the call to
- // ExecutableWriter::createImplicitFiles(), these symbols are never added
- // and ExectuableWriter::finalizeDefaultAtomValues() will crash if we call
- // it.
- OutputELFWriter<ELF64LE>::finalizeDefaultAtomValues();
-}
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h
deleted file mode 100644
index accc00b8a054..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef AMDGPU_EXECUTABLE_WRITER_H
-#define AMDGPU_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-#include "AMDGPULinkingContext.h"
-#include "AMDGPUSymbolTable.h"
-#include "AMDGPUTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-class AMDGPUTargetLayout;
-
-class AMDGPUExecutableWriter : public ExecutableWriter<ELF64LE> {
-public:
- AMDGPUExecutableWriter(AMDGPULinkingContext &ctx, AMDGPUTargetLayout &layout);
-
- unique_bump_ptr<SymbolTable<ELF64LE>> createSymbolTable() override {
- return unique_bump_ptr<SymbolTable<ELF64LE>>(new (this->_alloc)
- AMDGPUSymbolTable(_ctx));
- }
-
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &Result) override;
- void finalizeDefaultAtomValues() override;
-
-private:
- AMDGPULinkingContext &_ctx;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // AMDGPU_EXECUTABLE_WRITER_H
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp
deleted file mode 100644
index b1e83641fa82..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===------------------------------------------------------------------------===//
-
-#include "AMDGPULinkingContext.h"
-#include "AMDGPUTargetHandler.h"
-
-namespace lld {
-namespace elf {
-
-std::unique_ptr<ELFLinkingContext>
-createAMDGPULinkingContext(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::amdgcn)
- return llvm::make_unique<AMDGPULinkingContext>(triple);
- return nullptr;
-}
-
-AMDGPULinkingContext::AMDGPULinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, llvm::make_unique<AMDGPUTargetHandler>(*this)) {
-}
-
-static const Registry::KindStrings kindStrings[] = {LLD_KIND_STRING_END};
-
-void AMDGPULinkingContext::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::AMDGPU, kindStrings);
-}
-
-void setAMDGPUELFHeader(ELFHeader<ELF64LE> &elfHeader) {
- elfHeader.e_ident(llvm::ELF::EI_OSABI, ELFOSABI_AMDGPU_HSA);
-}
-
-StringRef AMDGPULinkingContext::entrySymbolName() const { return ""; }
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h
deleted file mode 100644
index 1cc7a3c7694f..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
-
-#include "OutputELFWriter.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-class AMDGPULinkingContext final : public ELFLinkingContext {
-public:
- AMDGPULinkingContext(llvm::Triple triple);
- int getMachineType() const override { return llvm::ELF::EM_AMDGPU; }
-
- void registerRelocationNames(Registry &r) override;
-
- StringRef entrySymbolName() const override;
-};
-
-void setAMDGPUELFHeader(ELFHeader<ELF64LE> &elfHeader);
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp
deleted file mode 100644
index ca5a77db9177..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp -----------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AMDGPURelocationHandler.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-std::error_code AMDGPUTargetRelocationHandler::applyRelocation(
- ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
- const Reference &ref) const {
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h
deleted file mode 100644
index 90d37274aebf..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- lld/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_RELOCATION_HANDLER_H
-#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_RELOCATION_HANDLER_H
-
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include <system_error>
-
-namespace lld {
-namespace elf {
-class AMDGPUTargetHandler;
-class AMDGPUTargetLayout;
-
-class AMDGPUTargetRelocationHandler final : public TargetRelocationHandler {
-public:
- AMDGPUTargetRelocationHandler(AMDGPUTargetLayout &layout) { }
-
- std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const AtomLayout &,
- const Reference &) const override;
-
-};
-} // elf
-} // lld
-#endif
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp
deleted file mode 100644
index 0824974d4602..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp ----------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AMDGPUSymbolTable.h"
-#include "ELFFile.h"
-#include "Atoms.h"
-#include "SectionChunks.h"
-
-using namespace lld;
-using namespace lld::elf;
-
-AMDGPUSymbolTable::AMDGPUSymbolTable(const ELFLinkingContext &ctx)
- : SymbolTable(ctx, ".symtab", TargetLayout<ELF64LE>::ORDER_SYMBOL_TABLE) {}
-
-void AMDGPUSymbolTable::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) {
- SymbolTable::addDefinedAtom(sym, da, addr);
-
- // FIXME: Only do this for kernel functions.
- sym.setType(STT_AMDGPU_HSA_KERNEL);
-
- // Make st_value section relative.
- // FIXME: This is hack to give kernel symbols a section relative offset.
- // Because of this hack only on kernel can be included in a binary file.
- sym.st_value = 0;
-}
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h
deleted file mode 100644
index 41c3be5cb38f..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h ------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_SYMBOL_TABLE_H
-#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_SYMBOL_TABLE_H
-
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-
-/// \brief The SymbolTable class represents the symbol table in a ELF file
-class AMDGPUSymbolTable : public SymbolTable<ELF64LE> {
-public:
- typedef llvm::object::Elf_Sym_Impl<ELF64LE> Elf_Sym;
-
- AMDGPUSymbolTable(const ELFLinkingContext &ctx);
-
- void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) override;
-};
-
-} // elf
-} // lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp
deleted file mode 100644
index ff4b600158bd..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp -------*- C++ -*-===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "TargetLayout.h"
-#include "AMDGPUExecutableWriter.h"
-#include "AMDGPULinkingContext.h"
-#include "AMDGPUTargetHandler.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-
-AMDGPUTargetHandler::AMDGPUTargetHandler(AMDGPULinkingContext &ctx)
- : _ctx(ctx), _targetLayout(new AMDGPUTargetLayout(ctx)),
- _relocationHandler(new AMDGPUTargetRelocationHandler(*_targetLayout)) {}
-
-std::unique_ptr<Writer> AMDGPUTargetHandler::getWriter() {
- switch (_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return llvm::make_unique<AMDGPUExecutableWriter>(_ctx, *_targetLayout);
- case llvm::ELF::ET_DYN:
- llvm_unreachable("TODO: support dynamic libraries");
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
-}
-
-HSATextSection::HSATextSection(const ELFLinkingContext &ctx)
- : AtomSection(ctx, ".hsatext", DefinedAtom::typeCode, 0, 0) {
- _type = SHT_PROGBITS;
- _flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR | SHF_AMDGPU_HSA_AGENT |
- SHF_AMDGPU_HSA_CODE;
-
- // FIXME: What alignment should we use here?
- _alignment = 4096;
-}
-
-void AMDGPUTargetLayout::assignSectionsToSegments() {
-
- TargetLayout::assignSectionsToSegments();
- for (OutputSection<ELF64LE> *osi : _outputSections) {
- for (Section<ELF64LE> *section : osi->sections()) {
- StringRef InputSectionName = section->inputSectionName();
- if (InputSectionName != ".hsatext")
- continue;
-
- auto *segment = new (_allocator) Segment<ELF64LE>(
- _ctx, "PT_AMDGPU_HSA_LOAD_CODE_AGENT", PT_AMDGPU_HSA_LOAD_CODE_AGENT);
- _segments.push_back(segment);
- assert(segment);
- segment->append(section);
- }
- }
-}
-
-} // namespace elf
-} // namespace lld
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h
deleted file mode 100644
index 8d0f70b6e7f7..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h ------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef AMDGPU_TARGET_HANDLER_H
-#define AMDGPU_TARGET_HANDLER_H
-
-#include "ELFFile.h"
-#include "ELFReader.h"
-#include "AMDGPURelocationHandler.h"
-#include "TargetLayout.h"
-
-namespace lld {
-namespace elf {
-class AMDGPULinkingContext;
-
-class HSATextSection : public AtomSection<ELF64LE> {
-public:
- HSATextSection(const ELFLinkingContext &ctx);
-};
-
-/// \brief TargetLayout for AMDGPU
-class AMDGPUTargetLayout final : public TargetLayout<ELF64LE> {
-public:
- AMDGPUTargetLayout(AMDGPULinkingContext &ctx) : TargetLayout(ctx) {}
-
- void assignSectionsToSegments() override;
-
- /// \brief Gets or creates a section.
- AtomSection<ELF64LE> *
- createSection(StringRef name, int32_t contentType,
- DefinedAtom::ContentPermissions contentPermissions,
- TargetLayout::SectionOrder sectionOrder) override {
- if (name == ".hsatext")
- return new (_allocator) HSATextSection(_ctx);
-
- if (name == ".note")
- contentType = DefinedAtom::typeRONote;
-
- return TargetLayout::createSection(name, contentType, contentPermissions,
- sectionOrder);
- }
-};
-
-/// \brief TargetHandler for AMDGPU
-class AMDGPUTargetHandler final : public TargetHandler {
-public:
- AMDGPUTargetHandler(AMDGPULinkingContext &targetInfo);
-
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Reader> getObjReader() override {
- return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
- }
-
- std::unique_ptr<Reader> getDSOReader() override {
- return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
- }
-
- std::unique_ptr<Writer> getWriter() override;
-
-private:
- AMDGPULinkingContext &_ctx;
- std::unique_ptr<AMDGPUTargetLayout> _targetLayout;
- std::unique_ptr<AMDGPUTargetRelocationHandler> _relocationHandler;
-};
-
-void finalizeAMDGPURuntimeAtomValues(AMDGPUTargetLayout &layout);
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt b/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt
deleted file mode 100644
index 9c9cc10fe397..000000000000
--- a/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-add_llvm_library(lldAMDGPUELFTarget
- AMDGPUExecutableWriter.cpp
- AMDGPULinkingContext.cpp
- AMDGPURelocationHandler.cpp
- AMDGPUSymbolTable.cpp
- AMDGPUTargetHandler.cpp
- LINK_LIBS
- lldELF
- lldReaderWriter
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/ELF/ARM/CMakeLists.txt b/lib/ReaderWriter/ELF/ARM/CMakeLists.txt
index 2ccf9eb6266d..c8cd6533d902 100644
--- a/lib/ReaderWriter/ELF/ARM/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/ARM/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldARMELFTarget
+add_lld_library(lldARMELFTarget
ARMLinkingContext.cpp
ARMTargetHandler.cpp
ARMRelocationHandler.cpp
diff --git a/lib/ReaderWriter/ELF/CMakeLists.txt b/lib/ReaderWriter/ELF/CMakeLists.txt
index e3e4a02b2810..3bc338507db6 100644
--- a/lib/ReaderWriter/ELF/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldELF
+add_lld_library(lldELF
Atoms.cpp
DynamicFile.cpp
ELFFile.cpp
@@ -27,4 +27,3 @@ add_subdirectory(Mips)
add_subdirectory(Hexagon)
add_subdirectory(AArch64)
add_subdirectory(ARM)
-add_subdirectory(AMDGPU)
diff --git a/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
index 2904c7b0dae0..70d6d618207d 100644
--- a/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
@@ -61,8 +61,6 @@ uint16_t ELFLinkingContext::getOutputMachine() const {
return llvm::ELF::EM_AARCH64;
case llvm::Triple::arm:
return llvm::ELF::EM_ARM;
- case llvm::Triple::amdgcn:
- return llvm::ELF::EM_AMDGPU;
default:
llvm_unreachable("Unhandled arch");
}
diff --git a/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt b/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt
index 6928f43c5459..e5c5cb77f38c 100644
--- a/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldHexagonELFTarget
+add_lld_library(lldHexagonELFTarget
HexagonLinkingContext.cpp
HexagonRelocationHandler.cpp
HexagonTargetHandler.cpp
diff --git a/lib/ReaderWriter/ELF/Mips/CMakeLists.txt b/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
index 434e310640bd..fd52a08ad2d8 100644
--- a/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldMipsELFTarget
+add_lld_library(lldMipsELFTarget
MipsAbiInfoHandler.cpp
MipsCtorsOrderPass.cpp
MipsELFFile.cpp
diff --git a/lib/ReaderWriter/ELF/X86/CMakeLists.txt b/lib/ReaderWriter/ELF/X86/CMakeLists.txt
index 191f7ab3d61d..5e3fe64dc15d 100644
--- a/lib/ReaderWriter/ELF/X86/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/X86/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldX86ELFTarget
+add_lld_library(lldX86ELFTarget
X86LinkingContext.cpp
X86TargetHandler.cpp
X86RelocationHandler.cpp
diff --git a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
index 36ea839aa674..61f4b4b524e8 100644
--- a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldX86_64ELFTarget
+add_lld_library(lldX86_64ELFTarget
X86_64LinkingContext.cpp
X86_64TargetHandler.cpp
X86_64RelocationHandler.cpp
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt
index d13c98008e55..700b2550b119 100644
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldExampleSubTarget
+add_lld_library(lldExampleSubTarget
ExampleLinkingContext.cpp
ExampleTargetHandler.cpp
LINK_LIBS
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index 0ba590cc6422..778f6f4add74 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -687,17 +687,28 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
case delta64:
*loc64 = ref.addend() + inAtomAddress - fixupAddress;
return;
+ case unwindFDEToFunction:
+ // We don't emit unwindFDEToFunction in -r mode as they are implicitly
+ // generated from the data in the __eh_frame section. So here we need
+ // to use the targetAddress so that we can generate the full relocation
+ // when we parse again later.
+ *loc64 = targetAddress - fixupAddress;
+ return;
case delta32:
*loc32 = ref.addend() + inAtomAddress - fixupAddress;
return;
case negDelta32:
+ // We don't emit negDelta32 in -r mode as they are implicitly
+ // generated from the data in the __eh_frame section. So here we need
+ // to use the targetAddress so that we can generate the full relocation
+ // when we parse again later.
*loc32 = fixupAddress - targetAddress + ref.addend();
return;
case pointer64ToGOT:
*loc64 = 0;
return;
case delta32ToGOT:
- *loc32 = -fixupAddress;
+ *loc32 = inAtomAddress - fixupAddress;
return;
case addOffset12:
llvm_unreachable("lazy reference kind implies GOT pass was run");
@@ -709,9 +720,6 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
case unwindInfoToEhFrame:
llvm_unreachable("fixup implies __unwind_info");
return;
- case unwindFDEToFunction:
- // Do nothing for now
- return;
case invalid:
// Fall into llvm_unreachable().
break;
diff --git a/lib/ReaderWriter/MachO/CMakeLists.txt b/lib/ReaderWriter/MachO/CMakeLists.txt
index 7ce782af6f99..a389ca51ddfd 100644
--- a/lib/ReaderWriter/MachO/CMakeLists.txt
+++ b/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldMachO
+add_lld_library(lldMachO
ArchHandler.cpp
ArchHandler_arm.cpp
ArchHandler_arm64.cpp
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
index 613c1b2f251a..1226860b021e 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
@@ -168,7 +168,8 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
StringRef &segmentName,
StringRef &sectionName,
SectionType &sectionType,
- SectionAttr &sectionAttrs);
+ SectionAttr &sectionAttrs,
+ bool &relocsToDefinedCanBeImplicit);
} // namespace normalized
} // namespace mach_o
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index e830db9fcc7b..575bc1a2b3a9 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -50,7 +50,8 @@ struct AtomInfo {
struct SectionInfo {
SectionInfo(StringRef seg, StringRef sect, SectionType type,
- const MachOLinkingContext &ctxt, uint32_t attr=0);
+ const MachOLinkingContext &ctxt, uint32_t attr,
+ bool relocsToDefinedCanBeImplicit);
StringRef segmentName;
StringRef sectionName;
@@ -59,15 +60,25 @@ struct SectionInfo {
uint64_t address;
uint64_t size;
uint16_t alignment;
+
+ /// If this is set, the any relocs in this section which point to defined
+ /// addresses can be implicitly generated. This is the case for the
+ /// __eh_frame section where references to the function can be implicit if the
+ /// function is defined.
+ bool relocsToDefinedCanBeImplicit;
+
+
std::vector<AtomInfo> atomsAndOffsets;
uint32_t normalizedSectionIndex;
uint32_t finalSectionIndex;
};
SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
- const MachOLinkingContext &ctxt, uint32_t attrs)
+ const MachOLinkingContext &ctxt, uint32_t attrs,
+ bool relocsToDefinedCanBeImplicit)
: segmentName(sg), sectionName(sct), type(t), attributes(attrs),
address(0), size(0), alignment(1),
+ relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit),
normalizedSectionIndex(0), finalSectionIndex(0) {
uint16_t align = 1;
if (ctxt.sectionAligned(segmentName, sectionName, align)) {
@@ -193,10 +204,12 @@ SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
StringRef sectionName;
SectionType sectionType;
SectionAttr sectionAttrs;
+ bool relocsToDefinedCanBeImplicit;
// Use same table used by when parsing .o files.
relocatableSectionInfoForContentType(type, segmentName, sectionName,
- sectionType, sectionAttrs);
+ sectionType, sectionAttrs,
+ relocsToDefinedCanBeImplicit);
// If we already have a SectionInfo with this name, re-use it.
// This can happen if two ContentType map to the same mach-o section.
for (auto sect : _sectionMap) {
@@ -207,7 +220,8 @@ SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
}
// Otherwise allocate new SectionInfo object.
auto *sect = new (_allocator)
- SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs);
+ SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs,
+ relocsToDefinedCanBeImplicit);
_sectionInfos.push_back(sect);
_sectionMap[type] = sect;
return sect;
@@ -287,7 +301,8 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
}
// Otherwise allocate new SectionInfo object.
auto *sect = new (_allocator) SectionInfo(
- p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs);
+ p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs,
+ /* relocsToDefinedCanBeImplicit */ false);
_sectionInfos.push_back(sect);
_sectionMap[atomType] = sect;
return sect;
@@ -320,7 +335,8 @@ SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
StringRef segName = customName.slice(0, seperatorIndex);
StringRef sectName = customName.drop_front(seperatorIndex + 1);
auto *sect =
- new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx);
+ new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx,
+ 0, /* relocsToDefinedCanBeImplicit */ false);
_customSections.push_back(sect);
_sectionInfos.push_back(sect);
return sect;
@@ -1024,6 +1040,11 @@ void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
for (const AtomInfo &info : si->atomsAndOffsets) {
const DefinedAtom *atom = info.atom;
for (const Reference *ref : *atom) {
+ // Skip emitting relocs for sections which are always able to be
+ // implicitly regenerated and where the relocation targets an address
+ // which is defined.
+ if (si->relocsToDefinedCanBeImplicit && isa<DefinedAtom>(ref->target()))
+ continue;
_archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
symIndexForAtom,
sectIndexForAtom,
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 1c4bb1d4f6a3..f9499b603214 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -1034,7 +1034,8 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
StringRef &segmentName,
StringRef &sectionName,
SectionType &sectionType,
- SectionAttr &sectionAttrs) {
+ SectionAttr &sectionAttrs,
+ bool &relocsToDefinedCanBeImplicit) {
for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
p->atomType != DefinedAtom::typeUnknown; ++p) {
@@ -1047,8 +1048,11 @@ void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
sectionName = p->sectionName;
sectionType = p->sectionType;
sectionAttrs = 0;
+ relocsToDefinedCanBeImplicit = false;
if (atomType == DefinedAtom::typeCode)
sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
+ if (atomType == DefinedAtom::typeCFI)
+ relocsToDefinedCanBeImplicit = true;
return;
}
llvm_unreachable("content type not yet supported");
diff --git a/lib/ReaderWriter/YAML/CMakeLists.txt b/lib/ReaderWriter/YAML/CMakeLists.txt
index b955baa94202..5c25444e5dbc 100644
--- a/lib/ReaderWriter/YAML/CMakeLists.txt
+++ b/lib/ReaderWriter/YAML/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_llvm_library(lldYAML
+add_lld_library(lldYAML
ReaderWriterYAML.cpp
LINK_LIBS
lldCore
diff --git a/test/COFF/export.test b/test/COFF/export.test
index a3ea0ab9bca2..20e069ec3c83 100644
--- a/test/COFF/export.test
+++ b/test/COFF/export.test
@@ -80,3 +80,14 @@ SYMTAB: __imp_exportfn2 in export.test.tmp.DLL
SYMTAB: exportfn2 in export.test.tmp.DLL
SYMTAB: __imp_exportfn3 in export.test.tmp.DLL
SYMTAB: exportfn3 in export.test.tmp.DLL
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:foo=kernel32.foobar
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=FORWARDER %s
+
+FORWARDER: Export Table:
+FORWARDER: DLL name: export.test.tmp.dll
+FORWARDER: Ordinal base: 0
+FORWARDER: Ordinal RVA Name
+FORWARDER: 0 0
+FORWARDER: 1 0x1010 exportfn
+FORWARDER: 2 foo (forwarded to kernel32.foobar)
diff --git a/test/ELF/Inputs/aarch64-condb-reloc.s b/test/ELF/Inputs/aarch64-condb-reloc.s
new file mode 100644
index 000000000000..ebe4923224c7
--- /dev/null
+++ b/test/ELF/Inputs/aarch64-condb-reloc.s
@@ -0,0 +1,17 @@
+.globl _foo
+_foo:
+ nop
+ nop
+ nop
+ nop
+
+.globl _bar
+_bar:
+ nop
+ nop
+ nop
+
+.globl _dah
+_dah:
+ nop
+ nop
diff --git a/test/ELF/Inputs/aarch64-tls-ie.s b/test/ELF/Inputs/aarch64-tls-ie.s
new file mode 100644
index 000000000000..c5e853ba9798
--- /dev/null
+++ b/test/ELF/Inputs/aarch64-tls-ie.s
@@ -0,0 +1,19 @@
+.text
+ .global foo
+ .section .tdata,"awT",%progbits
+ .align 2
+ .type foo, %object
+ .size foo, 4
+foo:
+ .word 5
+ .text
+
+.text
+ .global bar
+ .section .tdata,"awT",%progbits
+ .align 2
+ .type bar, %object
+ .size bar, 4
+bar:
+ .word 5
+ .text
diff --git a/test/ELF/Inputs/aarch64-tstbr14-reloc.s b/test/ELF/Inputs/aarch64-tstbr14-reloc.s
new file mode 100644
index 000000000000..64dc44033845
--- /dev/null
+++ b/test/ELF/Inputs/aarch64-tstbr14-reloc.s
@@ -0,0 +1,12 @@
+.globl _foo
+_foo:
+ nop
+ nop
+ nop
+ nop
+
+.globl _bar
+_bar:
+ nop
+ nop
+ nop
diff --git a/test/ELF/Inputs/mips-gp-disp.so b/test/ELF/Inputs/mips-gp-disp.so
new file mode 100644
index 000000000000..9cbb43720606
--- /dev/null
+++ b/test/ELF/Inputs/mips-gp-disp.so
Binary files differ
diff --git a/test/ELF/Inputs/wrap.s b/test/ELF/Inputs/wrap.s
new file mode 100644
index 000000000000..584e27033d5c
--- /dev/null
+++ b/test/ELF/Inputs/wrap.s
@@ -0,0 +1,4 @@
+.globl foo, __wrap_foo, __real_foo
+foo = 0x11000
+__wrap_foo = 0x11010
+__real_foo = 0x11020
diff --git a/test/ELF/aarch64-condb-reloc.s b/test/ELF/aarch64-condb-reloc.s
new file mode 100644
index 000000000000..630e3430f4e5
--- /dev/null
+++ b/test/ELF/aarch64-condb-reloc.s
@@ -0,0 +1,99 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-condb-reloc.s -o %t1
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t2
+# RUN: ld.lld %t1 %t2 -o %t
+# RUN: llvm-objdump -d %t | FileCheck %s
+# RUN: ld.lld -shared %t1 %t2 -o %t3
+# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s
+# RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
+# REQUIRES: aarch64
+
+# 0x11024 - 36 = 0x11000
+# 0x11028 - 24 = 0x11010
+# 0x1102c - 16 = 0x1101c
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: _foo:
+# CHECK-NEXT: 11000: {{.*}} nop
+# CHECK-NEXT: 11004: {{.*}} nop
+# CHECK-NEXT: 11008: {{.*}} nop
+# CHECK-NEXT: 1100c: {{.*}} nop
+# CHECK: _bar:
+# CHECK-NEXT: 11010: {{.*}} nop
+# CHECK-NEXT: 11014: {{.*}} nop
+# CHECK-NEXT: 11018: {{.*}} nop
+# CHECK: _dah:
+# CHECK-NEXT: 1101c: {{.*}} nop
+# CHECK-NEXT: 11020: {{.*}} nop
+# CHECK: _start:
+# CHECK-NEXT: 11024: {{.*}} b.eq #-36
+# CHECK-NEXT: 11028: {{.*}} b.eq #-24
+# CHECK-NEXT: 1102c: {{.*}} b.eq #-16
+
+#DSOREL: Section {
+#DSOREL: Index:
+#DSOREL: Name: .got.plt
+#DSOREL-NEXT: Type: SHT_PROGBITS
+#DSOREL-NEXT: Flags [
+#DSOREL-NEXT: SHF_ALLOC
+#DSOREL-NEXT: SHF_WRITE
+#DSOREL-NEXT: ]
+#DSOREL-NEXT: Address: 0x3000
+#DSOREL-NEXT: Offset: 0x3000
+#DSOREL-NEXT: Size: 48
+#DSOREL-NEXT: Link: 0
+#DSOREL-NEXT: Info: 0
+#DSOREL-NEXT: AddressAlignment: 8
+#DSOREL-NEXT: EntrySize: 0
+#DSOREL-NEXT: }
+#DSOREL: Relocations [
+#DSOREL-NEXT: Section ({{.*}}) .rela.plt {
+#DSOREL-NEXT: 0x3018 R_AARCH64_JUMP_SLOT _foo
+#DSOREL-NEXT: 0x3020 R_AARCH64_JUMP_SLOT _bar
+#DSOREL-NEXT: 0x3028 R_AARCH64_JUMP_SLOT _dah
+#DSOREL-NEXT: }
+#DSOREL-NEXT:]
+
+#DSO: Disassembly of section .text:
+#DSO-NEXT: _foo:
+#DSO-NEXT: 1000: {{.*}} nop
+#DSO-NEXT: 1004: {{.*}} nop
+#DSO-NEXT: 1008: {{.*}} nop
+#DSO-NEXT: 100c: {{.*}} nop
+#DSO: _bar:
+#DSO-NEXT: 1010: {{.*}} nop
+#DSO-NEXT: 1014: {{.*}} nop
+#DSO-NEXT: 1018: {{.*}} nop
+#DSO: _dah:
+#DSO-NEXT: 101c: {{.*}} nop
+#DSO-NEXT: 1020: {{.*}} nop
+#DSO: _start:
+#DSO-NEXT: 1024: {{.*}} b.eq #44
+#DSO-NEXT: 1028: {{.*}} b.eq #56
+#DSO-NEXT: 102c: {{.*}} b.eq #68
+#DSO-NEXT: Disassembly of section .plt:
+#DSO-NEXT: .plt:
+#DSO-NEXT: 1030: {{.*}} stp x16, x30, [sp, #-16]!
+#DSO-NEXT: 1034: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1038: {{.*}} ldr x17, [x16, #16]
+#DSO-NEXT: 103c: {{.*}} add x16, x16, #16
+#DSO-NEXT: 1040: {{.*}} br x17
+#DSO-NEXT: 1044: {{.*}} nop
+#DSO-NEXT: 1048: {{.*}} nop
+#DSO-NEXT: 104c: {{.*}} nop
+#DSO-NEXT: 1050: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1054: {{.*}} ldr x17, [x16, #24]
+#DSO-NEXT: 1058: {{.*}} add x16, x16, #24
+#DSO-NEXT: 105c: {{.*}} br x17
+#DSO-NEXT: 1060: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1064: {{.*}} ldr x17, [x16, #32]
+#DSO-NEXT: 1068: {{.*}} add x16, x16, #32
+#DSO-NEXT: 106c: {{.*}} br x17
+#DSO-NEXT: 1070: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1074: {{.*}} ldr x17, [x16, #40]
+#DSO-NEXT: 1078: {{.*}} add x16, x16, #40
+#DSO-NEXT: 107c: {{.*}} br x17
+
+.globl _start
+_start:
+ b.eq _foo
+ b.eq _bar
+ b.eq _dah
diff --git a/test/ELF/aarch64-gnu-ifunc-nosym.s b/test/ELF/aarch64-gnu-ifunc-nosym.s
new file mode 100644
index 000000000000..d85bf1076601
--- /dev/null
+++ b/test/ELF/aarch64-gnu-ifunc-nosym.s
@@ -0,0 +1,29 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-readobj -symbols %tout | FileCheck %s
+// REQUIRES: aarch64
+
+// Check that no __rela_iplt_end/__rela_iplt_start
+// appear in symtab if there is no references to them.
+// CHECK: Symbols [
+// CHECK-NEXT-NOT: __rela_iplt_end
+// CHECK-NEXT-NOT: __rela_iplt_start
+// CHECK: ]
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+.type bar, @function
+bar:
+ ret
+
+.globl _start
+_start:
+ bl foo
+ bl bar
diff --git a/test/ELF/aarch64-gnu-ifunc.s b/test/ELF/aarch64-gnu-ifunc.s
new file mode 100644
index 000000000000..4cc94200789d
--- /dev/null
+++ b/test/ELF/aarch64-gnu-ifunc.s
@@ -0,0 +1,144 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
+// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s --check-prefix=CHECK
+// REQUIRES: aarch64
+
+// CHECK: Sections [
+// CHECK: Section {
+// CHECK: Index: 1
+// CHECK-NEXT: Name: .rela.plt
+// CHECK-NEXT: Type: SHT_RELA
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[RELA:.*]]
+// CHECK-NEXT: Offset: 0x158
+// CHECK-NEXT: Size: 48
+// CHECK-NEXT: Link: 5
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 24
+// CHECK-NEXT: }
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: 0x12018 R_AARCH64_IRELATIVE
+// CHECK-NEXT: 0x12020 R_AARCH64_IRELATIVE
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK: Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name:
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: $x.0
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __rela_iplt_end
+// CHECK-NEXT: Value: 0x10188
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __rela_iplt_start
+// CHECK-NEXT: Value: 0x10158
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// CHECK-NEXT: Value: 0x11008
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: bar
+// CHECK-NEXT: Value: 0x11004
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: GNU_IFunc
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// 344 = 0x158
+// 392 = 0x188
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT: 11000: c0 03 5f d6 ret
+// DISASM: bar:
+// DISASM-NEXT: 11004: c0 03 5f d6 ret
+// DISASM: _start:
+// DISASM-NEXT: 11008: 0e 00 00 94 bl #56
+// DISASM-NEXT: 1100c: 11 00 00 94 bl #68
+// DISASM-NEXT: 11010: 42 60 05 91 add x2, x2, #344
+// DISASM-NEXT: 11014: 42 20 06 91 add x2, x2, #392
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 11020: f0 7b bf a9 stp x16, x30, [sp, #-16]!
+// DISASM-NEXT: 11024: 10 00 00 b0 adrp x16, #4096
+// DISASM-NEXT: 11028: 11 0a 40 f9 ldr x17, [x16, #16]
+// DISASM-NEXT: 1102c: 10 42 00 91 add x16, x16, #16
+// DISASM-NEXT: 11030: 20 02 1f d6 br x17
+// DISASM-NEXT: 11034: 1f 20 03 d5 nop
+// DISASM-NEXT: 11038: 1f 20 03 d5 nop
+// DISASM-NEXT: 1103c: 1f 20 03 d5 nop
+// DISASM-NEXT: 11040: 10 00 00 b0 adrp x16, #4096
+// DISASM-NEXT: 11044: 11 0e 40 f9 ldr x17, [x16, #24]
+// DISASM-NEXT: 11048: 10 62 00 91 add x16, x16, #24
+// DISASM-NEXT: 1104c: 20 02 1f d6 br x17
+// DISASM-NEXT: 11050: 10 00 00 b0 adrp x16, #4096
+// DISASM-NEXT: 11054: 11 12 40 f9 ldr x17, [x16, #32]
+// DISASM-NEXT: 11058: 10 82 00 91 add x16, x16, #32
+// DISASM-NEXT: 1105c: 20 02 1f d6 br x17
+
+.text
+.type foo STT_GNU_IFUNC
+.globl foo
+.type foo, @function
+foo:
+ ret
+
+.type bar STT_GNU_IFUNC
+.globl bar
+.type bar, @function
+bar:
+ ret
+
+.globl _start
+_start:
+ bl foo
+ bl bar
+ add x2, x2, :lo12:__rela_iplt_start
+ add x2, x2, :lo12:__rela_iplt_end
diff --git a/test/ELF/aarch64-tls-ie.s b/test/ELF/aarch64-tls-ie.s
new file mode 100644
index 000000000000..0462addba22d
--- /dev/null
+++ b/test/ELF/aarch64-tls-ie.s
@@ -0,0 +1,49 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
+# RUN: ld.lld -shared %tdso.o -o %tdso.so
+# RUN: ld.lld %tmain.o %tdso.so -o %tout
+# RUN: llvm-objdump -d %tout | FileCheck %s
+# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s
+# REQUIRES: aarch64
+
+#RELOC: Section {
+#RELOC: Index:
+#RELOC: Name: .got
+#RELOC-NEXT: Type: SHT_PROGBITS
+#RELOC-NEXT: Flags [
+#RELOC-NEXT: SHF_ALLOC
+#RELOC-NEXT: SHF_WRITE
+#RELOC-NEXT: ]
+#RELOC-NEXT: Address: 0x120B0
+#RELOC-NEXT: Offset: 0x20B0
+#RELOC-NEXT: Size: 16
+#RELOC-NEXT: Link: 0
+#RELOC-NEXT: Info: 0
+#RELOC-NEXT: AddressAlignment: 8
+#RELOC-NEXT: EntrySize: 0
+#RELOC-NEXT: }
+#RELOC: Relocations [
+#RELOC-NEXT: Section ({{.*}}) .rela.dyn {
+#RELOC-NEXT: 0x120B0 R_AARCH64_TLS_TPREL64 foo 0x0
+#RELOC-NEXT: 0x120B8 R_AARCH64_TLS_TPREL64 bar 0x0
+#RELOC-NEXT: }
+#RELOC-NEXT:]
+
+# Page(0x120B0) - Page(0x11000) = 0x1000 = 4096
+# 0x120B0 & 0xff8 = 0xB0 = 176
+# Page(0x120B8) - Page(0x11000) = 0x1000 = 4096
+# 0x120B8 & 0xff8 = 0xB8 = 184
+#CHECK: Disassembly of section .text:
+#CHECK: _start:
+#CHECK: 11000: 00 00 00 b0 adrp x0, #4096
+#CHECK: 11004: 00 58 40 f9 ldr x0, [x0, #176]
+#CHECK: 11008: 00 00 00 b0 adrp x0, #4096
+#CHECK: 1100c: 00 5c 40 f9 ldr x0, [x0, #184]
+
+.globl _start
+_start:
+ adrp x0, :gottprel:foo
+ ldr x0, [x0, #:gottprel_lo12:foo]
+
+ adrp x0, :gottprel:bar
+ ldr x0, [x0, #:gottprel_lo12:bar]
diff --git a/test/ELF/aarch64-tstbr14-reloc.s b/test/ELF/aarch64-tstbr14-reloc.s
new file mode 100644
index 000000000000..1dc1bdf3c09a
--- /dev/null
+++ b/test/ELF/aarch64-tstbr14-reloc.s
@@ -0,0 +1,96 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tstbr14-reloc.s -o %t1
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t2
+# RUN: ld.lld %t1 %t2 -o %t
+# RUN: llvm-objdump -d %t | FileCheck %s
+# RUN: ld.lld -shared %t1 %t2 -o %t3
+# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s
+# RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s
+# REQUIRES: aarch64
+
+# 0x1101c - 28 = 0x11000
+# 0x11020 - 16 = 0x11010
+# 0x11024 - 36 = 0x11000
+# 0x11028 - 24 = 0x11010
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: _foo:
+# CHECK-NEXT: 11000: {{.*}} nop
+# CHECK-NEXT: 11004: {{.*}} nop
+# CHECK-NEXT: 11008: {{.*}} nop
+# CHECK-NEXT: 1100c: {{.*}} nop
+# CHECK: _bar:
+# CHECK-NEXT: 11010: {{.*}} nop
+# CHECK-NEXT: 11014: {{.*}} nop
+# CHECK-NEXT: 11018: {{.*}} nop
+# CHECK: _start:
+# CHECK-NEXT: 1101c: {{.*}} tbnz w3, #15, #-28
+# CHECK-NEXT: 11020: {{.*}} tbnz w3, #15, #-16
+# CHECK-NEXT: 11024: {{.*}} tbz x6, #45, #-36
+# CHECK-NEXT: 11028: {{.*}} tbz x6, #45, #-24
+
+#DSOREL: Section {
+#DSOREL: Index:
+#DSOREL: Name: .got.plt
+#DSOREL-NEXT: Type: SHT_PROGBITS
+#DSOREL-NEXT: Flags [
+#DSOREL-NEXT: SHF_ALLOC
+#DSOREL-NEXT: SHF_WRITE
+#DSOREL-NEXT: ]
+#DSOREL-NEXT: Address: 0x3000
+#DSOREL-NEXT: Offset: 0x3000
+#DSOREL-NEXT: Size: 40
+#DSOREL-NEXT: Link: 0
+#DSOREL-NEXT: Info: 0
+#DSOREL-NEXT: AddressAlignment: 8
+#DSOREL-NEXT: EntrySize: 0
+#DSOREL-NEXT: }
+#DSOREL: Relocations [
+#DSOREL-NEXT: Section ({{.*}}) .rela.plt {
+#DSOREL-NEXT: 0x3018 R_AARCH64_JUMP_SLOT _foo
+#DSOREL-NEXT: 0x3020 R_AARCH64_JUMP_SLOT _bar
+#DSOREL-NEXT: }
+#DSOREL-NEXT:]
+
+#DSO: Disassembly of section .text:
+#DSO-NEXT: _foo:
+#DSO-NEXT: 1000: {{.*}} nop
+#DSO-NEXT: 1004: {{.*}} nop
+#DSO-NEXT: 1008: {{.*}} nop
+#DSO-NEXT: 100c: {{.*}} nop
+#DSO: _bar:
+#DSO-NEXT: 1010: {{.*}} nop
+#DSO-NEXT: 1014: {{.*}} nop
+#DSO-NEXT: 1018: {{.*}} nop
+#DSO: _start:
+# 0x101c + 52 = 0x1050 = PLT[1]
+# 0x1020 + 64 = 0x1060 = PLT[2]
+# 0x1024 + 44 = 0x1050 = PLT[1]
+# 0x1028 + 56 = 0x1060 = PLT[2]
+#DSO-NEXT: 101c: {{.*}} tbnz w3, #15, #52
+#DSO-NEXT: 1020: {{.*}} tbnz w3, #15, #64
+#DSO-NEXT: 1024: {{.*}} tbz x6, #45, #44
+#DSO-NEXT: 1028: {{.*}} tbz x6, #45, #56
+#DSO-NEXT: Disassembly of section .plt:
+#DSO-NEXT: .plt:
+#DSO-NEXT: 1030: {{.*}} stp x16, x30, [sp, #-16]!
+#DSO-NEXT: 1034: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1038: {{.*}} ldr x17, [x16, #16]
+#DSO-NEXT: 103c: {{.*}} add x16, x16, #16
+#DSO-NEXT: 1040: {{.*}} br x17
+#DSO-NEXT: 1044: {{.*}} nop
+#DSO-NEXT: 1048: {{.*}} nop
+#DSO-NEXT: 104c: {{.*}} nop
+#DSO-NEXT: 1050: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1054: {{.*}} ldr x17, [x16, #24]
+#DSO-NEXT: 1058: {{.*}} add x16, x16, #24
+#DSO-NEXT: 105c: {{.*}} br x17
+#DSO-NEXT: 1060: {{.*}} adrp x16, #8192
+#DSO-NEXT: 1064: {{.*}} ldr x17, [x16, #32]
+#DSO-NEXT: 1068: {{.*}} add x16, x16, #32
+#DSO-NEXT: 106c: {{.*}} br x17
+
+.globl _start
+_start:
+ tbnz w3, #15, _foo
+ tbnz w3, #15, _bar
+ tbz x6, #45, _foo
+ tbz x6, #45, _bar
diff --git a/test/ELF/amdgpu-entry.s b/test/ELF/amdgpu-entry.s
new file mode 100644
index 000000000000..a17d243214b7
--- /dev/null
+++ b/test/ELF/amdgpu-entry.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
+# RUN: not lld -e kernel0 -flavor gnu %t.o -o %t
+
+# REQUIRES: amdgpu
+
+.hsa_code_object_version 1,0
+.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"
+
+.hsatext
+.globl kernel0
+.align 256
+.amdgpu_hsa_kernel kernel0
+kernel0:
+ s_endpgm
+.Lfunc_end0:
+ .size kernel0, .Lfunc_end0-kernel0
diff --git a/test/ELF/amdgpu-globals.s b/test/ELF/amdgpu-globals.s
new file mode 100644
index 000000000000..ff0899f60a98
--- /dev/null
+++ b/test/ELF/amdgpu-globals.s
@@ -0,0 +1,138 @@
+# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
+# RUN: lld -flavor gnu %t.o -o %t
+# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
+
+# REQUIRES: amdgpu
+
+ .amdgpu_hsa_module_global module_global_program
+ .size module_global_program, 4
+ .hsadata_global_program
+module_global_program:
+ .long 0 ; 0x0
+
+ .amdgpu_hsa_program_global program_global_program
+ .size program_global_program, 4
+ .hsadata_global_program
+program_global_program:
+ .long 0 ; 0x0
+
+ .amdgpu_hsa_module_global module_global_agent
+ .size module_global_agent, 4
+ .hsadata_global_agent
+module_global_agent:
+ .long 0 ; 0x0
+
+ .amdgpu_hsa_program_global program_global_agent
+ .size program_global_agent, 4
+ .hsadata_global_agent
+program_global_agent:
+ .long 0 ; 0x0
+
+ .amdgpu_hsa_module_global module_global_readonly
+ .size module_global_readonly, 4
+ .hsatext
+module_global_readonly:
+ .long 0 ; 0x0
+
+ .amdgpu_hsa_program_global program_global_readonly
+ .size program_global_readonly, 4
+ .hsatext
+program_global_readonly:
+ .long 0 ; 0x0
+
+# CHECK: Section {
+# CHECK: Name: .hsadata_global_program
+# CHECK: Type: SHT_PROGBITS (0x1)
+# CHECK: Flags [ (0x100003)
+# CHECK: SHF_ALLOC (0x2)
+# CHECK: SHF_AMDGPU_HSA_GLOBAL (0x100000)
+# CHECK: SHF_WRITE (0x1)
+# CHECK: ]
+# CHECK: Address: [[HSADATA_GLOBAL_PROGRAM_ADDR:[0-9xa-f]+]]
+# CHECK: }
+
+# CHECK: Section {
+# CHECK: Name: .hsadata_global_agent
+# CHECK: Type: SHT_PROGBITS (0x1)
+# CHECK: Flags [ (0x900003)
+# CHECK: SHF_ALLOC (0x2)
+# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
+# CHECK: SHF_AMDGPU_HSA_GLOBAL (0x100000)
+# CHECK: SHF_WRITE (0x1)
+# CHECK: ]
+# CHECK: }
+
+# CHECK: Section {
+# CHECK: Name: .hsatext
+# CHECK: Type: SHT_PROGBITS
+# CHECK: Flags [ (0xC00007)
+# CHECK: SHF_ALLOC (0x2)
+# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
+# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
+# CHECK: SHF_EXECINSTR (0x4)
+# CHECK: SHF_WRITE (0x1)
+# CHECK: ]
+# CHECK: Address: [[HSATEXT_ADDR:[0-9xa-f]+]]
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: module_global_agent
+# CHECK: Value: 0x0
+# CHECK: Size: 4
+# CHECK: Binding: Local
+# CHECK: Section: .hsadata_global_agent
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: module_global_program
+# CHECK: Value: 0x0
+# CHECK: Size: 4
+# CHECK: Binding: Local
+# CHECK: Section: .hsadata_global_program
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: module_global_readonly
+# CHECK: Value: 0x0
+# CHECK: Size: 4
+# CHECK: Binding: Local
+# CHECK: Type: Object
+# CHECK: Section: .hsatext
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: program_global_agent
+# CHECK: Value: 0x4
+# CHECK: Size: 4
+# CHECK: Binding: Global
+# CHECK: Type: Object
+# CHECK: Section: .hsadata_global_agent
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: program_global_program
+# CHECK: Value: 0x4
+# CHECK: Size: 4
+# CHECK: Binding: Global
+# CHECK: Type: Object
+# CHECK: Section: .hsadata_global_program
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: program_global_readonly
+# CHECK: Value: 0x4
+# CHECK: Size: 4
+# CHECK: Binding: Global
+# CHECK: Type: Object
+# CHECK: Section: .hsatext
+# CHECK: }
+
+# CHECK: ProgramHeader {
+# CHECK: Type: PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM
+# CHECK: VirtualAddress: [[HSADATA_GLOBAL_PROGRAM_ADDR]]
+# CHECK: }
+
+# CHECK: ProgramHeader {
+# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT
+# CHECK: VirtualAddress: [[HSATEXT_ADDR]]
+# CHECK: }
diff --git a/test/ELF/amdgpu-kernels.s b/test/ELF/amdgpu-kernels.s
new file mode 100644
index 000000000000..3f43c71f65d7
--- /dev/null
+++ b/test/ELF/amdgpu-kernels.s
@@ -0,0 +1,63 @@
+# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
+# RUN: lld -flavor gnu %t.o -o %t
+# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s
+
+# REQUIRES: amdgpu
+
+.hsa_code_object_version 1,0
+.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"
+
+.hsatext
+.globl kernel0
+.align 256
+.amdgpu_hsa_kernel kernel0
+kernel0:
+ s_endpgm
+.Lfunc_end0:
+ .size kernel0, .Lfunc_end0-kernel0
+
+.globl kernel1
+.align 256
+.amdgpu_hsa_kernel kernel1
+kernel1:
+ s_endpgm
+ s_endpgm
+.Lfunc_end1:
+ .size kernel1, .Lfunc_end1-kernel1
+
+
+# CHECK: Section {
+# CHECK: Name: .hsatext
+# CHECK: Type: SHT_PROGBITS
+# CHECK: Flags [ (0xC00007)
+# CHECK: SHF_ALLOC (0x2)
+# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
+# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
+# CHECK: SHF_EXECINSTR (0x4)
+# CHECK: SHF_WRITE (0x1)
+# CHECK: ]
+# CHECK: Address: [[HSATEXT_ADDR:[0-9xa-f]+]]
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: kernel0
+# CHECK: Value: 0x0
+# CHECK: Size: 4
+# CHECK: Binding: Global
+# CHECK: Type: AMDGPU_HSA_KERNEL
+# CHECK: Section: .hsatext
+# CHECK: }
+
+# CHECK: Symbol {
+# CHECK: Name: kernel1
+# CHECK: Value: 0x100
+# CHECK: Size: 8
+# CHECK: Binding: Global
+# CHECK: Type: AMDGPU_HSA_KERNEL
+# CHECK: Section: .hsatext
+# CHECK: }
+
+# CHECK: ProgramHeader {
+# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT
+# CHECK: VirtualAddress: [[HSATEXT_ADDR]]
+# CHECK: }
diff --git a/test/ELF/basic-aarch64.s b/test/ELF/basic-aarch64.s
index 28fb10d82edf..61b6707e49a4 100644
--- a/test/ELF/basic-aarch64.s
+++ b/test/ELF/basic-aarch64.s
@@ -97,7 +97,7 @@ _start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 4
-# CHECK-NEXT: Name: .strtab (17)
+# CHECK-NEXT: Name: .strtab (25)
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
diff --git a/test/ELF/basic-mips.s b/test/ELF/basic-mips.s
index 0c8733f8c9c4..7b2ef564f1ce 100644
--- a/test/ELF/basic-mips.s
+++ b/test/ELF/basic-mips.s
@@ -87,7 +87,7 @@ __start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 3
-# CHECK-NEXT: Name: .text (1)
+# CHECK-NEXT: Name: .text (25)
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
# CHECK-NEXT: Flags [ (0x6)
# CHECK-NEXT: SHF_ALLOC (0x2)
@@ -119,7 +119,7 @@ __start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 5
-# CHECK-NEXT: Name: .bss (7)
+# CHECK-NEXT: Name: .bss (37)
# CHECK-NEXT: Type: SHT_NOBITS (0x8)
# CHECK-NEXT: Flags [ (0x3)
# CHECK-NEXT: SHF_ALLOC (0x2)
@@ -163,7 +163,7 @@ __start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 8
-# CHECK-NEXT: Name: .strtab (46)
+# CHECK-NEXT: Name: .strtab (60)
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
diff --git a/test/ELF/basic-ppc.s b/test/ELF/basic-ppc.s
new file mode 100644
index 000000000000..90acd8d8ddac
--- /dev/null
+++ b/test/ELF/basic-ppc.s
@@ -0,0 +1,296 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t
+# RUN: ld.lld -discard-all -shared %t -o %t2
+# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s
+# REQUIRES: ppc
+
+# exits with return code 42 on FreeBSD
+.text
+ li 0,1
+ li 3,1
+ sc
+
+// CHECK: Format: ELF32-ppc
+// CHECK-NEXT: Arch: powerpc
+// CHECK-NEXT: AddressSize: 32bit
+// CHECK-NEXT: LoadName:
+// CHECK-NEXT: ElfHeader {
+// CHECK-NEXT: Ident {
+// CHECK-NEXT: Magic: (7F 45 4C 46)
+// CHECK-NEXT: Class: 32-bit (0x1)
+// CHECK-NEXT: DataEncoding: BigEndian (0x2)
+// CHECK-NEXT: FileVersion: 1
+// CHECK-NEXT: OS/ABI: FreeBSD (0x9)
+// CHECK-NEXT: ABIVersion: 0
+// CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+// CHECK-NEXT: }
+// CHECK-NEXT: Type: SharedObject (0x3)
+// CHECK-NEXT: Machine: EM_PPC (0x14)
+// CHECK-NEXT: Version: 1
+// CHECK-NEXT: Entry: 0x0
+// CHECK-NEXT: ProgramHeaderOffset: 0x34
+// CHECK-NEXT: SectionHeaderOffset: 0x2084
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: HeaderSize: 52
+// CHECK-NEXT: ProgramHeaderEntrySize: 32
+// CHECK-NEXT: ProgramHeaderCount: 7
+// CHECK-NEXT: SectionHeaderEntrySize: 40
+// CHECK-NEXT: SectionHeaderCount: 9
+// CHECK-NEXT: StringTableSectionIndex: 7
+// CHECK-NEXT: }
+// CHECK-NEXT: Sections [
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 0
+// CHECK-NEXT: Name: (0)
+// CHECK-NEXT: Type: SHT_NULL (0x0)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 0
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 1
+// CHECK-NEXT: Name: .dynsym (1)
+// CHECK-NEXT: Type: SHT_DYNSYM (0xB)
+// CHECK-NEXT: Flags [ (0x2)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x114
+// CHECK-NEXT: Offset: 0x114
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 3
+// CHECK-NEXT: Info: 1
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 16
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 2
+// CHECK-NEXT: Name: .hash (9)
+// CHECK-NEXT: Type: SHT_HASH (0x5)
+// CHECK-NEXT: Flags [ (0x2)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x124
+// CHECK-NEXT: Offset: 0x124
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 1
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 4
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000001 00000001 00000000 00000000 |................|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 3
+// CHECK-NEXT: Name: .dynstr (15)
+// CHECK-NEXT: Type: SHT_STRTAB (0x3)
+// CHECK-NEXT: Flags [ (0x2)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x134
+// CHECK-NEXT: Offset: 0x134
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00 |.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 4
+// CHECK-NEXT: Name: .text (23)
+// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_EXECINSTR (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1000
+// CHECK-NEXT: Offset: 0x1000
+// CHECK-NEXT: Size: 12
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 38000001 38600001 44000002 |8...8`..D...|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 5
+// CHECK-NEXT: Name: .dynamic (29)
+// CHECK-NEXT: Type: SHT_DYNAMIC (0x6)
+// CHECK-NEXT: Flags [ (0x3)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_WRITE (0x1)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x2000
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: Size: 48
+// CHECK-NEXT: Link: 3
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 8
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000006 00000114 0000000B 00000010 |................|
+// CHECK-NEXT: 0010: 00000005 00000134 0000000A 00000001 |.......4........|
+// CHECK-NEXT: 0020: 00000004 00000124 00000000 00000000 |.......$........|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 6
+// CHECK-NEXT: Name: .symtab (38)
+// CHECK-NEXT: Type: SHT_SYMTAB (0x2)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset: 0x2030
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 8
+// CHECK-NEXT: Info: 1
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 16
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 7
+// CHECK-NEXT: Name: .shstrtab (46)
+// CHECK-NEXT: Type: SHT_STRTAB (0x3)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset: 0x2040
+// CHECK-NEXT: Size: 64
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 002E6479 6E73796D 002E6861 7368002E |..dynsym..hash..|
+// CHECK-NEXT: 0010: 64796E73 7472002E 74657874 002E6479 |dynstr..text..dy|
+// CHECK-NEXT: 0020: 6E616D69 63002E73 796D7461 62002E73 |namic..symtab..s|
+// CHECK-NEXT: 0030: 68737472 74616200 2E737472 74616200 |hstrtab..strtab.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 8
+// CHECK-NEXT: Name: .strtab (56)
+// CHECK-NEXT: Type: SHT_STRTAB (0x3)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset: 0x2080
+// CHECK-NEXT: Size: 1
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 00 |.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: ProgramHeaders [
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_PHDR (0x6)
+// CHECK-NEXT: Offset: 0x34
+// CHECK-NEXT: VirtualAddress: 0x34
+// CHECK-NEXT: PhysicalAddress: 0x34
+// CHECK-NEXT: FileSize: 224
+// CHECK-NEXT: MemSize: 224
+// CHECK-NEXT: Flags [ (0x4)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 8
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_LOAD (0x1)
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: VirtualAddress: 0x0
+// CHECK-NEXT: PhysicalAddress: 0x0
+// CHECK-NEXT: FileSize: 309
+// CHECK-NEXT: MemSize: 309
+// CHECK-NEXT: Flags [ (0x4)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 4096
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_LOAD (0x1)
+// CHECK-NEXT: Offset: 0x1000
+// CHECK-NEXT: VirtualAddress: 0x1000
+// CHECK-NEXT: PhysicalAddress: 0x1000
+// CHECK-NEXT: FileSize: 12
+// CHECK-NEXT: MemSize: 12
+// CHECK-NEXT: Flags [ (0x5)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: PF_X (0x1)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 4096
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_LOAD (0x1)
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: VirtualAddress: 0x2000
+// CHECK-NEXT: PhysicalAddress: 0x2000
+// CHECK-NEXT: FileSize: 48
+// CHECK-NEXT: MemSize: 48
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: PF_W (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 4096
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_DYNAMIC (0x2)
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: VirtualAddress: 0x2000
+// CHECK-NEXT: PhysicalAddress: 0x2000
+// CHECK-NEXT: FileSize: 48
+// CHECK-NEXT: MemSize: 48
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: PF_W (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 4
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_GNU_RELRO (0x6474E552)
+// CHECK-NEXT: Offset: 0x2000
+// CHECK-NEXT: VirtualAddress: 0x2000
+// CHECK-NEXT: PhysicalAddress: 0x2000
+// CHECK-NEXT: FileSize: 48
+// CHECK-NEXT: MemSize: 48
+// CHECK-NEXT: Flags [ (0x4)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 1
+// CHECK-NEXT: }
+// CHECK-NEXT: ProgramHeader {
+// CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
+// CHECK-NEXT: Offset: 0x0
+// CHECK-NEXT: VirtualAddress: 0x0
+// CHECK-NEXT: PhysicalAddress: 0x0
+// CHECK-NEXT: FileSize: 0
+// CHECK-NEXT: MemSize: 0
+// CHECK-NEXT: Flags [ (0x6)
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: PF_W (0x2)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/basic.s b/test/ELF/basic.s
index 47b28d41b5bb..bbc674ced2ed 100644
--- a/test/ELF/basic.s
+++ b/test/ELF/basic.s
@@ -98,7 +98,7 @@ _start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 4
-# CHECK-NEXT: Name: .strtab (17)
+# CHECK-NEXT: Name: .strtab (25)
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
diff --git a/test/ELF/basic32.s b/test/ELF/basic32.s
index e5b5c359d59f..f4f9c410a048 100644
--- a/test/ELF/basic32.s
+++ b/test/ELF/basic32.s
@@ -96,7 +96,7 @@ _start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 4
-# CHECK-NEXT: Name: .strtab (17)
+# CHECK-NEXT: Name: .strtab (25)
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
diff --git a/test/ELF/basic64be.s b/test/ELF/basic64be.s
index 9534e05b47e0..32d8974dae01 100644
--- a/test/ELF/basic64be.s
+++ b/test/ELF/basic64be.s
@@ -177,7 +177,7 @@ _start:
# CHECK-NEXT: }
# CHECK-NEXT: Section {
# CHECK-NEXT: Index: 7
-# CHECK-NEXT: Name: .strtab (27)
+# CHECK-NEXT: Name: .strtab (41)
# CHECK-NEXT: Type: SHT_STRTAB (0x3)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
@@ -257,4 +257,4 @@ _start:
# CHECK-NEXT: ]
# CHECK-NEXT: Alignment: 0
# CHECK-NEXT: }
-# CHECK-NEXT: ] \ No newline at end of file
+# CHECK-NEXT: ]
diff --git a/test/ELF/discard-none.s b/test/ELF/discard-none.s
index a9d54bae9ace..c13b544f514d 100644
--- a/test/ELF/discard-none.s
+++ b/test/ELF/discard-none.s
@@ -20,8 +20,8 @@
// CHECK-NEXT: AddressAlignment:
// CHECK-NEXT: EntrySize:
// CHECK-NEXT: SectionData (
-// CHECK-NEXT: 0000: 002E4C6D 79766172 002E4C6D 796F7468 |..Lmyvar..Lmyoth|
-// CHECK-NEXT: 0010: 65727661 7200 |ervar.|
+// CHECK-NEXT: 0000: 002E4C6D 796F7468 65727661 72002E4C |..Lmyothervar..L|
+// CHECK-NEXT: 0010: 6D797661 7200 |myvar.|
// CHECK-NEXT: )
// CHECK-NEXT: }
diff --git a/test/ELF/linkerscript-sections.s b/test/ELF/linkerscript-sections.s
index ea9ae2b2726d..165ec335ec13 100644
--- a/test/ELF/linkerscript-sections.s
+++ b/test/ELF/linkerscript-sections.s
@@ -22,7 +22,7 @@
# SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}}
+# SEC-DEFAULT: 7 .shstrtab 0000003c {{[0-9a-f]*}}
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
# Sections are put in order specified in linker script.
@@ -42,7 +42,7 @@
# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
-# SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}}
+# SEC-ORDER: 4 .shstrtab 0000003c {{[0-9a-f]*}}
# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
@@ -63,7 +63,7 @@
# SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-SWAP-NAMES: 7 .shstrtab 00000032 {{[0-9a-f]*}}
+# SEC-SWAP-NAMES: 7 .shstrtab 0000003c {{[0-9a-f]*}}
# SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}}
# .shstrtab from the input object file is discarded.
@@ -100,7 +100,7 @@
# SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}}
# SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-MULTI: 6 .shstrtab 0000002c {{[0-9a-f]*}}
+# SEC-MULTI: 6 .shstrtab 00000036 {{[0-9a-f]*}}
# SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}}
.globl _start;
diff --git a/test/ELF/mips-gp-disp.s b/test/ELF/mips-gp-disp.s
new file mode 100644
index 000000000000..a08829c18bd4
--- /dev/null
+++ b/test/ELF/mips-gp-disp.s
@@ -0,0 +1,34 @@
+# Check that even if _gp_disp symbol is defined in the shared library
+# we use our own value.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared -o %t.so %t.o %S/Inputs/mips-gp-disp.so
+# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=INT-SO %s
+# RUN: llvm-readobj -symbols %S/Inputs/mips-gp-disp.so \
+# RUN: | FileCheck -check-prefix=EXT-SO %s
+# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=DIS %s
+# RUN: llvm-readobj -relocations %t.so | FileCheck -check-prefix=REL %s
+
+# REQUIRES: mips
+
+# INT-SO-NOT: Name: _gp_disp
+
+# EXT-SO: Name: _gp_disp
+# EXT-SO-NEXT: Value: 0x20010
+
+# DIS: Disassembly of section .text:
+# DIS-NEXT: __start:
+# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1
+# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
+# ^-- 0x37ff0 & 0xffff
+# DIS: 00027ff0 *ABS* 00000000 _gp
+
+# REL: Relocations [
+# REL-NEXT: ]
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(_gp_disp)
+ addi $t0,$t0,%lo(_gp_disp)
+ lw $v0,%call16(_foo)($gp)
diff --git a/test/ELF/ppc-relocs.s b/test/ELF/ppc-relocs.s
new file mode 100644
index 000000000000..a70cac1615e0
--- /dev/null
+++ b/test/ELF/ppc-relocs.s
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck %s
+# REQUIRES: ppc
+
+.section .R_PPC_ADDR16_HA,"ax",@progbits
+.globl _start
+_start:
+ lis 4, msg@ha
+msg:
+ .string "foo"
+ len = . - msg
+
+# CHECK: Disassembly of section .R_PPC_ADDR16_HA:
+# CHECK: _start:
+# CHECK: 11000: 3c 80 00 01 lis 4, 1
+# CHECK: msg:
+# CHECK: 11004: 66 6f 6f 00 oris 15, 19, 28416
+
+.section .R_PPC_ADDR16_LO,"ax",@progbits
+ addi 4, 4, msg@l
+mystr:
+ .asciz "blah"
+ len = . - mystr
+
+# CHECK: Disassembly of section .R_PPC_ADDR16_LO:
+# CHECK: .R_PPC_ADDR16_LO:
+# CHECK: 11008: 38 84 10 04 addi 4, 4, 4100
+# CHECK: mystr:
+# CHECK: 1100c: 62 6c 61 68 ori 12, 19, 24936
diff --git a/test/ELF/relocation-copy.s b/test/ELF/relocation-copy.s
index 85cbf673910a..2e958ad5e955 100644
--- a/test/ELF/relocation-copy.s
+++ b/test/ELF/relocation-copy.s
@@ -2,18 +2,19 @@
// 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/relocation-copy.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t.so
-// RUN: ld.lld -e main %t.o %t.so -o %t3
+// RUN: ld.lld %t.o %t.so -o %t3
// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
.text
-.globl main
-.align 16, 0x90
-.type main,@function
-main:
+.global _start
+_start:
movl $5, x
movl $7, y
movl $9, z
+movl $x, %edx
+movl $y, %edx
+movl $z, %edx
// CHECK: Name: .bss
// CHECK-NEXT: Type: SHT_NOBITS (0x8)
@@ -57,7 +58,10 @@ movl $9, z
// 77840 = 0x13000 + 16
// 77844 = 0x13000 + 16 + 4
// CODE: Disassembly of section .text:
-// CODE-NEXT: main:
+// CODE-NEXT: _start:
// CODE-NEXT: 11000: c7 04 25 00 30 01 00 05 00 00 00 movl $5, 77824
// CODE-NEXT: 1100b: c7 04 25 10 30 01 00 07 00 00 00 movl $7, 77840
// CODE-NEXT: 11016: c7 04 25 14 30 01 00 09 00 00 00 movl $9, 77844
+// CODE-NEXT: 11021: ba 00 30 01 00 movl $77824, %edx
+// CODE-NEXT: 11026: ba 10 30 01 00 movl $77840, %edx
+// CODE-NEXT: 1102b: ba 14 30 01 00 movl $77844, %edx
diff --git a/test/ELF/string-table.s b/test/ELF/string-table.s
index 52a40d790d8f..8393d6de6cc5 100644
--- a/test/ELF/string-table.s
+++ b/test/ELF/string-table.s
@@ -58,9 +58,10 @@ _start:
// CHECK-NEXT: AddressAlignment: 1
// CHECK-NEXT: EntrySize: 0
// CHECK-NEXT: SectionData (
-// CHECK-NEXT: 0000: 002E7465 78740066 6F6F6261 72002E73 |..text.foobar..s|
-// CHECK-NEXT: 0010: 68737472 74616200 2E737472 74616200 |hstrtab..strtab.|
-// CHECK-NEXT: 0020: 2E73796D 74616200 |.symtab.|
+// CHECK-NEXT: 0000: 00626172 002E7465 78740066 6F6F6261 |.bar..text.fooba|
+// CHECK-NEXT: 0010: 7200666F 6F626172 00666F6F 62617200 |r.foobar.foobar.|
+// CHECK-NEXT: 0020: 2E73796D 74616200 2E736873 74727461 |.symtab..shstrta|
+// CHECK-NEXT: 0030: 62002E73 74727461 6200 |b..strtab.|
// CHECK-NEXT: )
// CHECK-NEXT:}
// CHECK: Name: .strtab
@@ -75,6 +76,6 @@ _start:
// CHECK-NEXT: AddressAlignment: 1
// CHECK-NEXT: EntrySize: 0
// CHECK-NEXT: SectionData (
-// CHECK-NEXT: 0000: 005F7374 61727400 666F6F62 617200 |._start.foobar.|
+// CHECK-NEXT: 0000: 00666F6F 62617200 5F737461 727400 |.foobar._start.|
// CHECK-NEXT: )
// CHECK-NEXT: }
diff --git a/test/ELF/wrap.s b/test/ELF/wrap.s
new file mode 100644
index 000000000000..17aac2db6e18
--- /dev/null
+++ b/test/ELF/wrap.s
@@ -0,0 +1,19 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap.s -o %t2
+
+// RUN: ld.lld -o %t3 %t %t2 -wrap foo -wrap nosuchsym
+// RUN: llvm-objdump -d -print-imm-hex %t3 | FileCheck %s
+// RUN: ld.lld -o %t3 %t %t2 --wrap foo -wrap=nosuchsym
+// RUN: llvm-objdump -d -print-imm-hex %t3 | FileCheck %s
+
+// CHECK: _start:
+// CHECK-NEXT: movl $0x11010, %edx
+// CHECK-NEXT: movl $0x11010, %edx
+// CHECK-NEXT: movl $0x11000, %edx
+
+.global _start
+_start:
+ movl $foo, %edx
+ movl $__wrap_foo, %edx
+ movl $__real_foo, %edx
diff --git a/test/lit.cfg b/test/lit.cfg
index 54e8c7f546f8..d8794039f152 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -227,6 +227,8 @@ if re.search(r'X86', archs):
config.available_features.add('x86')
if re.search(r'PowerPC', archs):
config.available_features.add('ppc')
+if re.search(r'AMDGPU', archs):
+ config.available_features.add('amdgpu')
llvm_config_cmd.wait()
# Check if Windows resource file compiler exists.
diff --git a/test/mach-o/arm64-reloc-negDelta32-fixup.yaml b/test/mach-o/arm64-reloc-negDelta32-fixup.yaml
index 8beab2841dc3..4da88097eb60 100644
--- a/test/mach-o/arm64-reloc-negDelta32-fixup.yaml
+++ b/test/mach-o/arm64-reloc-negDelta32-fixup.yaml
@@ -7,7 +7,7 @@
# We don't emit these in to the binary as relocations, so we need to
# make sure that the offset in the FDE to the CIE is the correct value.
# CHECK: {{[0-9abcdef]*}} 10000000 00000000 017a5200 01781e01
-# CHECK: {{[0-9abcdef]*}} 100c1f00 20000000 18000000 e4ffffff
+# CHECK: {{[0-9abcdef]*}} 100c1f00 20000000 18000000 b8ffffff
# Note, this one that matters ^~~~~~~~
# It needs to be 0x18 as that is the offset back to 0 where the CIE is.
# CHECK: {{[0-9abcdef]*}} ffffffff 20000000 00000000 00480e10
@@ -84,7 +84,7 @@ sections:
content: [ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x1E, 0x01,
0x10, 0x0C, 0x1F, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF,
+ 0x18, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0E, 0x10,
0x9E, 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00 ]
diff --git a/test/mach-o/do-not-emit-unwind-fde-arm64.yaml b/test/mach-o/do-not-emit-unwind-fde-arm64.yaml
new file mode 100644
index 000000000000..d306419bc5f9
--- /dev/null
+++ b/test/mach-o/do-not-emit-unwind-fde-arm64.yaml
@@ -0,0 +1,208 @@
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
+# RUN: lld -flavor darwin -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
+# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t | FileCheck -check-prefix=CODE %s
+# RUN: llvm-objdump -r -s -section="__eh_frame" -macho %t2 | FileCheck -check-prefix=CODE %s
+
+
+--- !mach-o
+arch: arm64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+compat-version: 0.0
+current-version: 0.0
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 4
+ address: 0x0000000000000000
+ content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
+ 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91,
+ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x80, 0x52,
+ 0xFD, 0x7B, 0xC1, 0xA8, 0xC0, 0x03, 0x5F, 0xD6 ]
+ relocations:
+ - offset: 0x00000010
+ type: ARM64_RELOC_BRANCH26
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 9
+ - offset: 0x0000000C
+ type: ARM64_RELOC_PAGEOFF12
+ length: 2
+ pc-rel: false
+ extern: true
+ symbol: 1
+ - offset: 0x00000008
+ type: ARM64_RELOC_PAGE21
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 1
+ - segment: __TEXT
+ section: __cstring
+ type: S_CSTRING_LITERALS
+ attributes: [ ]
+ address: 0x0000000000000020
+ content: [ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
+ 0x72, 0x6C, 0x64, 0x00 ]
+ - segment: __LD
+ section: __compact_unwind
+ type: S_REGULAR
+ attributes: [ ]
+ alignment: 8
+ address: 0x0000000000000030
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000000
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: false
+ symbol: 1
+ - segment: __TEXT
+ section: __eh_frame
+ type: S_COALESCED
+ attributes: [ ]
+ alignment: 8
+ address: 0x0000000000000050
+ content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
+ 0x1E, 0x0B, 0x00, 0xED, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0x0C, 0x1F, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x48, 0x0E, 0x10, 0x9E, 0x01, 0x9D, 0x02 ]
+ - segment: __TEXT
+ section: __gcc_except_tab
+ type: S_REGULAR
+ attributes: [ ]
+ address: 0x00000000000000A0
+ content: [ 0x00, 0x00, 0x00, 0x00 ]
+local-symbols:
+ - name: ltmp0
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000000
+ - name: L_str
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000020
+ - name: ltmp1
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000020
+ - name: ltmp2
+ type: N_SECT
+ sect: 3
+ value: 0x0000000000000030
+ - name: ltmp3
+ type: N_SECT
+ sect: 4
+ value: 0x0000000000000050
+ - name: ltmp4
+ type: N_SECT
+ sect: 4
+ value: 0x0000000000000070
+global-symbols:
+ - name: __Z3fooi
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: __gxx_personality_v0
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _bar
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _puts
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+page-size: 0x00000000
+
+# CHECK: defined-atoms:
+# CHECK: - ref-name: L{{[0-9]*}}
+# CHECK: scope: hidden
+# CHECK: type: c-string
+# CHECK: content: [ 48, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ]
+# CHECK: merge: by-content
+# CHECK: - ref-name: L{{[0-9]*}}
+# CHECK: type: unwind-cfi
+# CHECK: content: [ 1C, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 50, 4C,
+# CHECK: 52, 00, 01, 78, 1E, 0B, 00, ED, FF, FF, FF, FF,
+# CHECK: FF, FF, FF, 00, 10, 0C, 1F, 00 ]
+# CHECK: - type: unwind-cfi
+# CHECK: content: [ 24, 00, 00, 00, 24, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
+# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 20, 00, 00, 00, 00, 00, 00, 00,
+# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 48, 0E, 10,
+# CHECK: 9E, 01, 9D, 02 ]
+# CHECK: references:
+# CHECK: - kind: negDelta32
+# CHECK: offset: 4
+# CHECK: target: L{{[0-9]*}}
+# CHECK: - kind: unwindFDEToFunction
+# CHECK: offset: 8
+# CHECK: target: __Z3fooi
+# CHECK: - kind: unwindFDEToFunction
+# CHECK: offset: 25
+# CHECK: target: L{{[0-9]*}}
+# CHECK: - ref-name: L{{[0-9]*}}
+# CHECK: type: unwind-lsda
+# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: - type: compact-unwind
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 20, 00, 00, 00,
+# CHECK: 00, 00, 00, 03, 00, 00, 00, 00, 00, 00, 00, 00,
+# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK: alignment: 8
+# CHECK: references:
+# CHECK: - kind: pointer64
+# CHECK: offset: 0
+# CHECK: target: __Z3fooi
+# CHECK: - name: __Z3fooi
+# CHECK: scope: global
+# CHECK: content: [ FD, 7B, BF, A9, FD, 03, 00, 91, 00, 00, 00, 90,
+# CHECK: 00, 00, 00, 91, 00, 00, 00, 94, 00, 00, 80, 52,
+# CHECK: FD, 7B, C1, A8, C0, 03, 5F, D6 ]
+# CHECK: alignment: 4
+# CHECK: references:
+# CHECK: - kind: page21
+# CHECK: offset: 8
+# CHECK: target: L{{[0-9]*}}
+# CHECK: - kind: offset12
+# CHECK: offset: 12
+# CHECK: target: L{{[0-9]*}}
+# CHECK: - kind: branch26
+# CHECK: offset: 16
+# CHECK: target: _puts
+
+# Make sure we don't have any relocations in the __eh_frame section
+# CODE-NOT: RELOCATION RECORDS FOR [__eh_frame]
+
+# Also make sure the reloc for the FDE->function is the correct offset
+# It should be the offset from the fixup location back to the address
+# of the function we are referencing
+# CODE: Contents of section __eh_frame:
+# This is the CIE:
+# CODE-NEXT: {{[0-9abcdef]*}} 1c000000 00000000 017a504c 52000178
+# CODE-NEXT: {{[0-9abcdef]*}} 1e0b00ed ffffffff ffffff00 100c1f00
+# This is the FDE:
+# CODE-NEXT: {{[0-9abcdef]*}} 24000000 24000000 a8ffffff ffffffff
+# This is the important offset for FDE->func ^~~~~~~~ ~~~~~~~~
+
+# CODE-NEXT: {{[0-9abcdef]*}} 20000000 00000000 08c3ffff ffffffff
+# And this is the offset for FDE->lsda ^~~~~~~~ ~~~~~~
+# CODE-NEXT: {{[0-9abcdef]*}} ff480e10 9e019d02
+# And this byte ^~
diff --git a/test/mach-o/parse-data-relocs-arm64.yaml b/test/mach-o/parse-data-relocs-arm64.yaml
index d02422f6a6f9..0edd64689b2e 100644
--- a/test/mach-o/parse-data-relocs-arm64.yaml
+++ b/test/mach-o/parse-data-relocs-arm64.yaml
@@ -16,11 +16,18 @@ arch: arm64
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 4
+ address: 0x0000000000000000
+ content: [ 0xC0, 0x03, 0x5F, 0xD6 ]
- segment: __DATA
section: __data
type: S_REGULAR
attributes: [ ]
- address: 0x0000000000000000
+ address: 0x0000000000000004
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -28,7 +35,7 @@ sections:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC0, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF,
0xB0, 0xFF, 0xFF, 0xFF ]
@@ -38,107 +45,114 @@ sections:
length: 2
pc-rel: true
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x0000004C
type: ARM64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x0000004C
type: ARM64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000048
type: ARM64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000048
type: ARM64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000040
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000038
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: false
- symbol: 1
+ symbol: 2
- offset: 0x00000030
type: ARM64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000030
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000028
type: ARM64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000028
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000020
type: ARM64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000020
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000018
type: ARM64_RELOC_POINTER_TO_GOT
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000010
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
- offset: 0x00000008
type: ARM64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
- symbol: 1
+ symbol: 2
local-symbols:
- name: _v1
type: N_SECT
+ sect: 2
+ value: 0x000000000000000C
+global-symbols:
+ - name: _bar
+ type: N_SECT
+ scope: [ N_EXT ]
sect: 1
- value: 0x0000000000000008
+ value: 0x0000000000000000
undefined-symbols:
- name: _foo
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
+page-size: 0x00000000
...
# CHECK: defined-atoms:
@@ -151,9 +165,9 @@ undefined-symbols:
# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, E0, FF, FF, FF,
# CHECK: FF, FF, FF, FF, DC, FF, FF, FF, FF, FF, FF, FF,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
+# CHECK: {{..}}, {{..}}, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
# CHECK: 00, 00, 00, 00, C0, FF, FF, FF, BE, FF, FF, FF,
-# CHECK: B0, FF, FF, FF ]
+# CHECK: {{B0|B8}}, {{..}}, FF, FF ]
# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
@@ -199,11 +213,19 @@ undefined-symbols:
# CHECK: offset: 72
# CHECK: target: _foo
# CHECK-NOT: addend:
+# CHECK: - name: _bar
+# CHECK: scope: global
+# CHECK: content: [ C0, 03, 5F, D6 ]
+# CHECK: alignment: 4
# CHECK: undefined-atoms:
# CHECK: - name: _foo
-
-
+# .subsections_via_symbols
+# .text
+# .globl_foo
+# .align2
+# _foo:
+# ret
# .data
#Lanon:
# .quad 0
diff --git a/test/old-elf/AMDGPU/hsa.test b/test/old-elf/AMDGPU/hsa.test
deleted file mode 100644
index 4a17ae2223e0..000000000000
--- a/test/old-elf/AMDGPU/hsa.test
+++ /dev/null
@@ -1,53 +0,0 @@
-# RUN: yaml2obj -format=elf %s > %t.obj
-# RUN: lld -flavor old-gnu -target amdgcn--hsa %t.obj -o %t.exe --noinhibit-exec
-# RUN: llvm-readobj -h -program-headers -s -symbols %t.exe | FileCheck %s
-
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Class: 64-bit (0x2)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: Machine: EM_AMDGPU (0xE0)
-
-
-# CHECK: Section {
-# CHECK: Name: .hsatext
-# CHECK: Type: SHT_PROGBITS (0x1)
-# CHECK: Flags [ (0xC00007
-# CHECK: SHF_ALLOC (0x2)
-# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
-# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
-# CHECK: SHF_EXECINSTR (0x4)
-# CHECK: SHF_WRITE (0x1)
-#
-# CHECK: Symbol {
-# CHECK: Name: kernel
-# CHECK: Value: 0x0
-# CHECK: Binding: Local (0x0)
-# CHECK: Type: AMDGPU_HSA_KERNEL (0xA)
-
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT (0x60000003)
-
----
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_AMDGPU
-Sections:
- - Name: .hsatext
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: ''
- - Name: .note
- Type: SHT_NOTE
- AddressAlign: 0x0000000000000001
- Content: '00'
-Symbols:
- Local:
- - Name: kernel
- Type: STT_GNU_IFUNC
- Section: .hsatext
-...