diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-01-13 20:06:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-01-13 20:06:04 +0000 |
commit | b289257c7f3ed78b7d3971c596d7c60a9050c705 (patch) | |
tree | d6b57e29a5a86347a020d6f0cae76cc2d0f3bf8d | |
parent | fba2c04f31e119eacf142fcbbaabd5a9e63a39ed (diff) |
Notes
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 ®istry) { - 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 §ionName, SectionType §ionType, - SectionAttr §ionAttrs); + SectionAttr §ionAttrs, + 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 §ionName, SectionType §ionType, - SectionAttr §ionAttrs) { + SectionAttr §ionAttrs, + 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 Binary files differnew file mode 100644 index 000000000000..9cbb43720606 --- /dev/null +++ b/test/ELF/Inputs/mips-gp-disp.so 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 -... |