diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:58 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:58 +0000 |
commit | da06c7cfa0388de29a4024d8d386e48f2fb13ed6 (patch) | |
tree | dc28e84fc2bb9a4a4d9873fe4d04946fe3f7f4c0 | |
parent | 267829774358b5aebd3e726ae318813bd48129bb (diff) | |
download | src-test2-da06c7cfa0388de29a4024d8d386e48f2fb13ed6.tar.gz src-test2-da06c7cfa0388de29a4024d8d386e48f2fb13ed6.zip |
Notes
135 files changed, 1880 insertions, 398 deletions
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp index c0996f55f9d1..7d93c28c86c8 100644 --- a/COFF/Chunks.cpp +++ b/COFF/Chunks.cpp @@ -210,7 +210,15 @@ void SectionChunk::writeTo(uint8_t *Buf) const { memcpy(Buf + OutputSectionOff, A.data(), A.size()); // Apply relocations. + size_t InputSize = getSize(); for (const coff_relocation &Rel : Relocs) { + // Check for an invalid relocation offset. This check isn't perfect, because + // we don't have the relocation size, which is only known after checking the + // machine and relocation type. As a result, a relocation may overwrite the + // beginning of the following input section. + if (Rel.VirtualAddress >= InputSize) + fatal("relocation points beyond the end of its parent section"); + uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress; // Get the output section of the symbol for this relocation. The output @@ -227,7 +235,7 @@ void SectionChunk::writeTo(uint8_t *Buf) const { // sections are not GC roots and can end up with these kinds of relocations. // Skip these relocations. if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) { - if (isCodeView()) + if (isCodeView() || isDWARF()) continue; fatal("relocation against symbol in discarded section: " + Sym->getName()); diff --git a/COFF/Chunks.h b/COFF/Chunks.h index fc3f5d0df4b6..ece5419e255e 100644 --- a/COFF/Chunks.h +++ b/COFF/Chunks.h @@ -112,7 +112,7 @@ protected: }; // A chunk corresponding a section of an input file. -class SectionChunk : public Chunk { +class SectionChunk final : public Chunk { // Identical COMDAT Folding feature accesses section internal data. friend class ICF; @@ -188,6 +188,9 @@ public: return SectionName == ".debug" || SectionName.startswith(".debug$"); } + // True if this is a DWARF debug info chunk. + bool isDWARF() const { return SectionName.startswith(".debug_"); } + // Allow iteration over the bodies of this chunk's relocated symbols. llvm::iterator_range<symbol_iterator> symbols() const { return llvm::make_range(symbol_iterator(File, Relocs.begin()), diff --git a/COFF/Config.h b/COFF/Config.h index 25fdc7abd67b..a58e7d5585f2 100644 --- a/COFF/Config.h +++ b/COFF/Config.h @@ -82,6 +82,7 @@ struct Configuration { SymbolBody *Entry = nullptr; bool NoEntry = false; std::string OutputFile; + std::string ImportName; bool ColorDiagnostics; bool DoGC = true; bool DoICF = true; diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp index 3620297b8b94..35f4a04866c5 100644 --- a/COFF/Driver.cpp +++ b/COFF/Driver.cpp @@ -429,7 +429,32 @@ static std::string getImplibPath() { return Out.str(); } -static void createImportLibrary() { +// +// The import name is caculated as the following: +// +// | LIBRARY w/ ext | LIBRARY w/o ext | no LIBRARY +// -----+----------------+---------------------+------------------ +// LINK | {value} | {value}.{.dll/.exe} | {output name} +// LIB | {value} | {value}.dll | {output name}.dll +// +static std::string getImportName(bool AsLib) { + SmallString<128> Out; + + if (Config->ImportName.empty()) { + Out.assign(sys::path::filename(Config->OutputFile)); + if (AsLib) + sys::path::replace_extension(Out, ".dll"); + } else { + Out.assign(Config->ImportName); + if (!sys::path::has_extension(Out)) + sys::path::replace_extension(Out, + (Config->DLL || AsLib) ? ".dll" : ".exe"); + } + + return Out.str(); +} + +static void createImportLibrary(bool AsLib) { std::vector<COFFShortExport> Exports; for (Export &E1 : Config->Exports) { COFFShortExport E2; @@ -444,9 +469,8 @@ static void createImportLibrary() { Exports.push_back(E2); } - std::string DLLName = sys::path::filename(Config->OutputFile); - std::string Path = getImplibPath(); - writeImportLibrary(DLLName, Path, Exports, Config->Machine); + writeImportLibrary(getImportName(AsLib), getImplibPath(), Exports, + Config->Machine); } static void parseModuleDefs(StringRef Path) { @@ -457,6 +481,7 @@ static void parseModuleDefs(StringRef Path) { if (Config->OutputFile.empty()) Config->OutputFile = Saver.save(M.OutputFile); + Config->ImportName = Saver.save(M.ImportName); if (M.ImageBase) Config->ImageBase = M.ImageBase; if (M.StackReserve) @@ -992,7 +1017,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { // Handle generation of import library from a def file. if (!Args.hasArgNoClaim(OPT_INPUT)) { fixupExports(); - createImportLibrary(); + createImportLibrary(/*AsLib=*/true); exit(0); } @@ -1117,7 +1142,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { // need to create a .lib file. if (!Config->Exports.empty() || Config->DLL) { fixupExports(); - createImportLibrary(); + createImportLibrary(/*AsLib=*/false); assignExportOrdinals(); } diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp index 508f59e3af1f..89462da93454 100644 --- a/COFF/PDB.cpp +++ b/COFF/PDB.cpp @@ -14,28 +14,29 @@ #include "SymbolTable.h" #include "Symbols.h" #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" -#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/Object/COFF.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Endian.h" @@ -53,8 +54,81 @@ using llvm::object::coff_section; static ExitOnError ExitOnErr; +namespace { +/// Map from type index and item index in a type server PDB to the +/// corresponding index in the destination PDB. +struct CVIndexMap { + SmallVector<TypeIndex, 0> TPIMap; + SmallVector<TypeIndex, 0> IPIMap; + bool IsTypeServerMap = false; +}; + +class PDBLinker { +public: + PDBLinker(SymbolTable *Symtab) + : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), + IDTable(Alloc) {} + + /// Emit the basic PDB structure: initial streams, headers, etc. + void initialize(const llvm::codeview::DebugInfo *DI); + + /// Link CodeView from each object file in the symbol table into the PDB. + void addObjectsToPDB(); + + /// Link CodeView from a single object file into the PDB. + void addObjectFile(ObjectFile *File); + + /// Produce a mapping from the type and item indices used in the object + /// file to those in the destination PDB. + /// + /// If the object file uses a type server PDB (compiled with /Zi), merge TPI + /// and IPI from the type server PDB and return a map for it. Each unique type + /// server PDB is merged at most once, so this may return an existing index + /// mapping. + /// + /// If the object does not use a type server PDB (compiled with /Z7), we merge + /// all the type and item records from the .debug$S stream and fill in the + /// caller-provided ObjectIndexMap. + const CVIndexMap &mergeDebugT(ObjectFile *File, CVIndexMap &ObjectIndexMap); + + const CVIndexMap &maybeMergeTypeServerPDB(ObjectFile *File, + TypeServer2Record &TS); + + /// Add the section map and section contributions to the PDB. + void addSections(ArrayRef<uint8_t> SectionTable); + + /// Write the PDB to disk. + void commit(); + +private: + BumpPtrAllocator Alloc; + + SymbolTable *Symtab; + + pdb::PDBFileBuilder Builder; + + /// Type records that will go into the PDB TPI stream. + TypeTableBuilder TypeTable; + + /// Item records that will go into the PDB IPI stream. + TypeTableBuilder IDTable; + + /// PDBs use a single global string table for filenames in the file checksum + /// table. + DebugStringTableSubsection PDBStrTab; + + llvm::SmallString<128> NativePath; + + std::vector<pdb::SecMapEntry> SectionMap; + + /// Type index mappings of type server PDBs that we've loaded so far. + std::map<GUID, CVIndexMap> TypeServerIndexMappings; +}; +} + // Returns a list of all SectionChunks. -static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) { +static void addSectionContribs(SymbolTable *Symtab, + pdb::DbiStreamBuilder &DbiBuilder) { for (Chunk *C : Symtab->getChunks()) if (auto *SC = dyn_cast<SectionChunk>(C)) DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header); @@ -96,24 +170,115 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, }); } -static void mergeDebugT(ObjectFile *File, - TypeTableBuilder &IDTable, - TypeTableBuilder &TypeTable, - SmallVectorImpl<TypeIndex> &TypeIndexMap, - pdb::PDBTypeServerHandler &Handler) { +static Optional<TypeServer2Record> +maybeReadTypeServerRecord(CVTypeArray &Types) { + auto I = Types.begin(); + if (I == Types.end()) + return None; + const CVType &Type = *I; + if (Type.kind() != LF_TYPESERVER2) + return None; + TypeServer2Record TS; + if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS)) + fatal(EC, "error reading type server record"); + return std::move(TS); +} + +const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File, + CVIndexMap &ObjectIndexMap) { ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); if (Data.empty()) - return; + return ObjectIndexMap; BinaryByteStream Stream(Data, support::little); CVTypeArray Types; BinaryStreamReader Reader(Stream); - Handler.addSearchPath(sys::path::parent_path(File->getName())); if (auto EC = Reader.readArray(Types, Reader.getLength())) fatal(EC, "Reader::readArray failed"); + + // Look through type servers. If we've already seen this type server, don't + // merge any type information. + if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord(Types)) + return maybeMergeTypeServerPDB(File, *TS); + + // This is a /Z7 object. Fill in the temporary, caller-provided + // ObjectIndexMap. if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, - TypeIndexMap, &Handler, Types)) - fatal(Err, "codeview::mergeTypeStreams failed"); + ObjectIndexMap.TPIMap, Types)) + fatal(Err, "codeview::mergeTypeAndIdRecords failed"); + return ObjectIndexMap; +} + +static Expected<std::unique_ptr<pdb::NativeSession>> +tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { + std::unique_ptr<pdb::IPDBSession> ThisSession; + if (auto EC = + pdb::loadDataForPDB(pdb::PDB_ReaderType::Native, TSPath, ThisSession)) + return std::move(EC); + + std::unique_ptr<pdb::NativeSession> NS( + static_cast<pdb::NativeSession *>(ThisSession.release())); + pdb::PDBFile &File = NS->getPDBFile(); + auto ExpectedInfo = File.getPDBInfoStream(); + // All PDB Files should have an Info stream. + if (!ExpectedInfo) + return ExpectedInfo.takeError(); + + // Just because a file with a matching name was found and it was an actual + // PDB file doesn't mean it matches. For it to match the InfoStream's GUID + // must match the GUID specified in the TypeServer2 record. + if (ExpectedInfo->getGuid() != GuidFromObj) + return make_error<pdb::GenericError>( + pdb::generic_error_code::type_server_not_found, TSPath); + + return std::move(NS); +} + +const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File, + TypeServer2Record &TS) { + // First, check if we already loaded a PDB with this GUID. Return the type + // index mapping if we have it. + auto Insertion = TypeServerIndexMappings.insert({TS.getGuid(), CVIndexMap()}); + CVIndexMap &IndexMap = Insertion.first->second; + if (!Insertion.second) + return IndexMap; + + // Mark this map as a type server map. + IndexMap.IsTypeServerMap = true; + + // Check for a PDB at: + // 1. The given file path + // 2. Next to the object file or archive file + auto ExpectedSession = tryToLoadPDB(TS.getGuid(), TS.getName()); + if (!ExpectedSession) { + consumeError(ExpectedSession.takeError()); + StringRef LocalPath = + !File->ParentName.empty() ? File->ParentName : File->getName(); + SmallString<128> Path = sys::path::parent_path(LocalPath); + sys::path::append( + Path, sys::path::filename(TS.getName(), sys::path::Style::windows)); + ExpectedSession = tryToLoadPDB(TS.getGuid(), Path); + } + if (auto E = ExpectedSession.takeError()) + fatal(E, "Type server PDB was not found"); + + // Merge TPI first, because the IPI stream will reference type indices. + auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); + if (auto E = ExpectedTpi.takeError()) + fatal(E, "Type server does not have TPI stream"); + if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap, + ExpectedTpi->typeArray())) + fatal(Err, "codeview::mergeTypeRecords failed"); + + // Merge IPI. + auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream(); + if (auto E = ExpectedIpi.takeError()) + fatal(E, "Type server does not have TPI stream"); + if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap, + ExpectedIpi->typeArray())) + fatal(Err, "codeview::mergeIdRecords failed"); + + return IndexMap; } static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { @@ -127,16 +292,22 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { static void remapTypesInSymbolRecord(ObjectFile *File, MutableArrayRef<uint8_t> Contents, - ArrayRef<TypeIndex> TypeIndexMap, + const CVIndexMap &IndexMap, ArrayRef<TiReference> TypeRefs) { for (const TiReference &Ref : TypeRefs) { unsigned ByteSize = Ref.Count * sizeof(TypeIndex); if (Contents.size() < Ref.Offset + ByteSize) fatal("symbol record too short"); + + // This can be an item index or a type index. Choose the appropriate map. + ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap; + if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap) + TypeOrItemMap = IndexMap.IPIMap; + MutableArrayRef<TypeIndex> TIs( reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count); for (TypeIndex &TI : TIs) { - if (!remapTypeIndex(TI, TypeIndexMap)) { + if (!remapTypeIndex(TI, TypeOrItemMap)) { TI = TypeIndex(SimpleTypeKind::NotTranslated); log("ignoring symbol record in " + File->getName() + " with bad type index 0x" + utohexstr(TI.getIndex())); @@ -241,7 +412,7 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, } static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, - ArrayRef<TypeIndex> TypeIndexMap, + const CVIndexMap &IndexMap, BinaryStreamRef SymData) { // FIXME: Improve error recovery by warning and skipping records when // possible. @@ -264,7 +435,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, // Re-map all the type index references. MutableArrayRef<uint8_t> Contents = NewData.drop_front(sizeof(RecordPrefix)); - remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs); + remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs); // Fill in "Parent" and "End" fields by maintaining a stack of scopes. CVSymbol NewSym(Sym.kind(), NewData); @@ -289,110 +460,105 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc, ".debug$S"); } -// Add all object files to the PDB. Merge .debug$T sections into IpiData and -// TpiData. -static void addObjectsToPDB(BumpPtrAllocator &Alloc, SymbolTable *Symtab, - pdb::PDBFileBuilder &Builder, - TypeTableBuilder &TypeTable, - TypeTableBuilder &IDTable) { - // Follow type servers. If the same type server is encountered more than - // once for this instance of `PDBTypeServerHandler` (for example if many - // object files reference the same TypeServer), the types from the - // TypeServer will only be visited once. - pdb::PDBTypeServerHandler Handler; - - // PDBs use a single global string table for filenames in the file checksum - // table. - auto PDBStrTab = std::make_shared<DebugStringTableSubsection>(); - - // Visit all .debug$T sections to add them to Builder. - for (ObjectFile *File : Symtab->ObjectFiles) { - // Add a module descriptor for every object file. We need to put an absolute - // path to the object into the PDB. If this is a plain object, we make its - // path absolute. If it's an object in an archive, we make the archive path - // absolute. - bool InArchive = !File->ParentName.empty(); - SmallString<128> Path = InArchive ? File->ParentName : File->getName(); - sys::fs::make_absolute(Path); - sys::path::native(Path, llvm::sys::path::Style::windows); - StringRef Name = InArchive ? File->getName() : StringRef(Path); - - File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); - File->ModuleDBI->setObjFileName(Path); - - // Before we can process symbol substreams from .debug$S, we need to process - // type information, file checksums, and the string table. Add type info to - // the PDB first, so that we can get the map from object file type and item - // indices to PDB type and item indices. - SmallVector<TypeIndex, 128> TypeIndexMap; - mergeDebugT(File, IDTable, TypeTable, TypeIndexMap, Handler); - - // Now do all line info. - for (SectionChunk *DebugChunk : File->getDebugChunks()) { - if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S") - continue; +void PDBLinker::addObjectFile(ObjectFile *File) { + // Add a module descriptor for every object file. We need to put an absolute + // path to the object into the PDB. If this is a plain object, we make its + // path absolute. If it's an object in an archive, we make the archive path + // absolute. + bool InArchive = !File->ParentName.empty(); + SmallString<128> Path = InArchive ? File->ParentName : File->getName(); + sys::fs::make_absolute(Path); + sys::path::native(Path, sys::path::Style::windows); + StringRef Name = InArchive ? File->getName() : StringRef(Path); + + File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); + File->ModuleDBI->setObjFileName(Path); + + // Before we can process symbol substreams from .debug$S, we need to process + // type information, file checksums, and the string table. Add type info to + // the PDB first, so that we can get the map from object file type and item + // indices to PDB type and item indices. + CVIndexMap ObjectIndexMap; + const CVIndexMap &IndexMap = mergeDebugT(File, ObjectIndexMap); + + // Now do all live .debug$S sections. + for (SectionChunk *DebugChunk : File->getDebugChunks()) { + if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S") + continue; - ArrayRef<uint8_t> RelocatedDebugContents = - relocateDebugChunk(Alloc, DebugChunk); - if (RelocatedDebugContents.empty()) - continue; + ArrayRef<uint8_t> RelocatedDebugContents = + relocateDebugChunk(Alloc, DebugChunk); + if (RelocatedDebugContents.empty()) + continue; - DebugSubsectionArray Subsections; - BinaryStreamReader Reader(RelocatedDebugContents, support::little); - ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); - - DebugStringTableSubsectionRef CVStrTab; - DebugChecksumsSubsectionRef Checksums; - for (const DebugSubsectionRecord &SS : Subsections) { - switch (SS.kind()) { - case DebugSubsectionKind::StringTable: - ExitOnErr(CVStrTab.initialize(SS.getRecordData())); - break; - case DebugSubsectionKind::FileChecksums: - ExitOnErr(Checksums.initialize(SS.getRecordData())); - break; - case DebugSubsectionKind::Lines: - // We can add the relocated line table directly to the PDB without - // modification because the file checksum offsets will stay the same. - File->ModuleDBI->addDebugSubsection(SS); - break; - case DebugSubsectionKind::Symbols: - mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData()); - break; - default: - // FIXME: Process the rest of the subsections. - break; - } + DebugSubsectionArray Subsections; + BinaryStreamReader Reader(RelocatedDebugContents, support::little); + ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); + + DebugStringTableSubsectionRef CVStrTab; + DebugChecksumsSubsectionRef Checksums; + for (const DebugSubsectionRecord &SS : Subsections) { + switch (SS.kind()) { + case DebugSubsectionKind::StringTable: + ExitOnErr(CVStrTab.initialize(SS.getRecordData())); + break; + case DebugSubsectionKind::FileChecksums: + ExitOnErr(Checksums.initialize(SS.getRecordData())); + break; + case DebugSubsectionKind::Lines: + // We can add the relocated line table directly to the PDB without + // modification because the file checksum offsets will stay the same. + File->ModuleDBI->addDebugSubsection(SS); + break; + case DebugSubsectionKind::Symbols: + mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData()); + break; + default: + // FIXME: Process the rest of the subsections. + break; } + } - if (Checksums.valid()) { - // Make a new file checksum table that refers to offsets in the PDB-wide - // string table. Generally the string table subsection appears after the - // checksum table, so we have to do this after looping over all the - // subsections. - if (!CVStrTab.valid()) - fatal(".debug$S sections must have both a string table subsection " - "and a checksum subsection table or neither"); - auto NewChecksums = - make_unique<DebugChecksumsSubsection>(*PDBStrTab); - for (FileChecksumEntry &FC : Checksums) { - StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); - ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile( - *File->ModuleDBI, FileName)); - NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); - } - File->ModuleDBI->addDebugSubsection(std::move(NewChecksums)); + if (Checksums.valid()) { + // Make a new file checksum table that refers to offsets in the PDB-wide + // string table. Generally the string table subsection appears after the + // checksum table, so we have to do this after looping over all the + // subsections. + if (!CVStrTab.valid()) + fatal(".debug$S sections must have both a string table subsection " + "and a checksum subsection table or neither"); + auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab); + for (FileChecksumEntry &FC : Checksums) { + StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); + ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI, + FileName)); + NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); } + File->ModuleDBI->addDebugSubsection(std::move(NewChecksums)); } } +} + +// Add all object files to the PDB. Merge .debug$T sections into IpiData and +// TpiData. +void PDBLinker::addObjectsToPDB() { + for (ObjectFile *File : Symtab->ObjectFiles) + addObjectFile(File); - Builder.getStringTableBuilder().setStrings(*PDBStrTab); + Builder.getStringTableBuilder().setStrings(PDBStrTab); // Construct TPI stream contents. addTypeInfo(Builder.getTpiBuilder(), TypeTable); // Construct IPI stream contents. addTypeInfo(Builder.getIpiBuilder(), IDTable); + + // Add public and symbol records stream. + + // For now we don't actually write any thing useful to the publics stream, but + // the act of "getting" it also creates it lazily so that we write an empty + // stream. + (void)Builder.getPublicsBuilder(); } static void addLinkerModuleSymbols(StringRef Path, @@ -423,7 +589,7 @@ static void addLinkerModuleSymbols(StringRef Path, std::string ArgStr = llvm::join(Args, " "); EBS.Fields.push_back("cwd"); SmallString<64> cwd; - llvm::sys::fs::current_path(cwd); + sys::fs::current_path(cwd); EBS.Fields.push_back(cwd); EBS.Fields.push_back("exe"); EBS.Fields.push_back(Config->Argv[0]); @@ -442,8 +608,14 @@ static void addLinkerModuleSymbols(StringRef Path, // Creates a PDB file. void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, const llvm::codeview::DebugInfo *DI) { - BumpPtrAllocator Alloc; - pdb::PDBFileBuilder Builder(Alloc); + PDBLinker PDB(Symtab); + PDB.initialize(DI); + PDB.addObjectsToPDB(); + PDB.addSections(SectionTable); + PDB.commit(); +} + +void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) { ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize // Create streams in MSF for predefined streams, namely @@ -455,12 +627,7 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, auto &InfoBuilder = Builder.getInfoBuilder(); InfoBuilder.setAge(DI ? DI->PDB70.Age : 0); - llvm::SmallString<128> NativePath(Config->PDBPath.begin(), - Config->PDBPath.end()); - llvm::sys::fs::make_absolute(NativePath); - llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows); - - pdb::PDB_UniqueId uuid{}; + GUID uuid{}; if (DI) memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid)); InfoBuilder.setGuid(uuid); @@ -471,32 +638,25 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); DbiBuilder.setVersionHeader(pdb::PdbDbiV70); ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {})); +} - // It's not entirely clear what this is, but the * Linker * module uses it. - uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); - - TypeTableBuilder TypeTable(BAlloc); - TypeTableBuilder IDTable(BAlloc); - addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable); - - // Add public and symbol records stream. - - // For now we don't actually write any thing useful to the publics stream, but - // the act of "getting" it also creates it lazily so that we write an empty - // stream. - (void)Builder.getPublicsBuilder(); - +void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) { // Add Section Contributions. + pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); addSectionContribs(Symtab, DbiBuilder); // Add Section Map stream. ArrayRef<object::coff_section> Sections = { (const object::coff_section *)SectionTable.data(), SectionTable.size() / sizeof(object::coff_section)}; - std::vector<pdb::SecMapEntry> SectionMap = - pdb::DbiStreamBuilder::createSectionMap(Sections); + SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections); DbiBuilder.setSectionMap(SectionMap); + // It's not entirely clear what this is, but the * Linker * module uses it. + NativePath = Config->PDBPath; + sys::fs::make_absolute(NativePath); + sys::path::native(NativePath, sys::path::Style::windows); + uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); LinkerModule.setPdbFilePathNI(PdbFilePathNI); addLinkerModuleSymbols(NativePath, LinkerModule, Alloc); @@ -504,7 +664,9 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, // Add COFF section header stream. ExitOnErr( DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); +} +void PDBLinker::commit() { // Write to a file. ExitOnErr(Builder.commit(Config->PDBPath)); } diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp index e4b06ade4487..106021de7d32 100644 --- a/ELF/Arch/ARM.cpp +++ b/ELF/Arch/ARM.cpp @@ -40,6 +40,8 @@ public: void addPltHeaderSymbols(InputSectionBase *ISD) const override; bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const override; + bool inBranchRange(uint32_t RelocType, uint64_t Src, + uint64_t Dst) const override; void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; } // namespace @@ -218,6 +220,49 @@ bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, return false; } +bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const { + uint64_t Range; + uint64_t InstrSize; + + switch (RelocType) { + case R_ARM_PC24: + case R_ARM_PLT32: + case R_ARM_JUMP24: + case R_ARM_CALL: + Range = 0x2000000; + InstrSize = 4; + break; + case R_ARM_THM_JUMP19: + Range = 0x100000; + InstrSize = 2; + break; + case R_ARM_THM_JUMP24: + case R_ARM_THM_CALL: + Range = 0x1000000; + InstrSize = 2; + break; + default: + return true; + } + // PC at Src is 2 instructions ahead, immediate of branch is signed + if (Src > Dst) + Range -= 2 * InstrSize; + else + Range += InstrSize; + + if ((Dst & 0x1) == 0) + // Destination is ARM, if ARM caller then Src is already 4-byte aligned. + // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure + // destination will be 4 byte aligned. + Src &= ~0x3; + else + // Bit 0 == 1 denotes Thumb state, it is not part of the range + Dst &= ~0x1; + + uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src; + return Distance <= Range; +} + void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { switch (Type) { case R_ARM_ABS32: diff --git a/ELF/Arch/MipsArchTree.cpp b/ELF/Arch/MipsArchTree.cpp index ed183e9a3061..3d1dc1daf0c1 100644 --- a/ELF/Arch/MipsArchTree.cpp +++ b/ELF/Arch/MipsArchTree.cpp @@ -37,7 +37,7 @@ struct FileFlags { StringRef Filename; uint32_t Flags; }; -} +} // namespace static StringRef getAbiName(uint32_t Flags) { switch (Flags) { @@ -337,8 +337,8 @@ uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, return NewFlag; if (compareMipsFpAbi(OldFlag, NewFlag) < 0) error("target floating point ABI '" + getMipsFpAbiName(OldFlag) + - "' is incompatible with '" + getMipsFpAbiName(NewFlag) + "': " + - FileName); + "' is incompatible with '" + getMipsFpAbiName(NewFlag) + + "': " + FileName); return OldFlag; } diff --git a/ELF/Config.h b/ELF/Config.h index 5e3b77637316..23627dd812db 100644 --- a/ELF/Config.h +++ b/ELF/Config.h @@ -99,6 +99,7 @@ struct Configuration { std::vector<VersionDefinition> VersionDefinitions; std::vector<llvm::StringRef> Argv; std::vector<llvm::StringRef> AuxiliaryList; + std::vector<llvm::StringRef> FilterList; std::vector<llvm::StringRef> SearchPaths; std::vector<llvm::StringRef> SymbolOrderingFile; std::vector<llvm::StringRef> Undefined; diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index 10ad13f214d5..4630e110bcd8 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -259,6 +259,9 @@ static void checkOptions(opt::InputArgList &Args) { if (Config->Pie && Config->Shared) error("-shared and -pie may not be used together"); + if (!Config->Shared && !Config->FilterList.empty()) + error("-F may not be used without -shared"); + if (!Config->Shared && !Config->AuxiliaryList.empty()) error("-f may not be used without -shared"); @@ -631,6 +634,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); Config->FatalWarnings = getArg(Args, OPT_fatal_warnings, OPT_no_fatal_warnings, false); + Config->FilterList = getArgs(Args, OPT_filter); Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false); Config->GdbIndex = Args.hasArg(OPT_gdb_index); diff --git a/ELF/EhFrame.h b/ELF/EhFrame.h index 4e2b6f83a294..07d1aaa3cbb3 100644 --- a/ELF/EhFrame.h +++ b/ELF/EhFrame.h @@ -19,7 +19,7 @@ struct EhSectionPiece; template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off); template <class ELFT> uint8_t getFdeEncoding(EhSectionPiece *P); -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/Filesystem.h b/ELF/Filesystem.h index d56d067f7378..dbeadac5a96b 100644 --- a/ELF/Filesystem.h +++ b/ELF/Filesystem.h @@ -16,7 +16,7 @@ namespace lld { namespace elf { void unlinkAsync(StringRef Path); std::error_code tryCreateFile(StringRef Path); -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/GdbIndex.h b/ELF/GdbIndex.h index c49f8946e199..bc024e6689ef 100644 --- a/ELF/GdbIndex.h +++ b/ELF/GdbIndex.h @@ -11,8 +11,8 @@ #define LLD_ELF_GDB_INDEX_H #include "InputFiles.h" -#include "llvm/Object/ELF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Object/ELF.h" namespace lld { namespace elf { diff --git a/ELF/ICF.h b/ELF/ICF.h index 502e128c8109..24219855fc17 100644 --- a/ELF/ICF.h +++ b/ELF/ICF.h @@ -14,6 +14,6 @@ namespace lld { namespace elf { template <class ELFT> void doIcf(); } -} +} // namespace lld #endif diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index 544a0b009b39..f6d3f907850c 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -11,8 +11,8 @@ #define LLD_ELF_INPUT_FILES_H #include "Config.h" -#include "InputSection.h" #include "Error.h" +#include "InputSection.h" #include "Symbols.h" #include "lld/Core/LLVM.h" @@ -34,7 +34,7 @@ struct DILineInfo; namespace lto { class InputFile; } -} +} // namespace llvm namespace lld { namespace elf { diff --git a/ELF/LTO.h b/ELF/LTO.h index 28afa0e83add..d19923c90a99 100644 --- a/ELF/LTO.h +++ b/ELF/LTO.h @@ -30,7 +30,7 @@ namespace llvm { namespace lto { class LTO; } -} +} // namespace llvm namespace lld { namespace elf { @@ -51,7 +51,7 @@ private: std::vector<SmallString<0>> Buff; std::vector<std::unique_ptr<MemoryBuffer>> Files; }; -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index a182d5a3a096..8bdbd8db20ad 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -229,6 +229,19 @@ bool LinkerScript::shouldKeep(InputSectionBase *S) { return false; } +// If an input string is in the form of "foo.N" where N is a number, +// return N. Otherwise, returns 65536, which is one greater than the +// lowest priority. +static int getPriority(StringRef S) { + size_t Pos = S.rfind('.'); + if (Pos == StringRef::npos) + return 65536; + int V; + if (!to_integer(S.substr(Pos + 1), V, 10)) + return 65536; + return V; +} + // A helper function for the SORT() command. static std::function<bool(InputSectionBase *, InputSectionBase *)> getComparator(SortSectionPolicy K) { @@ -449,7 +462,7 @@ void LinkerScript::fabricateDefaultCommands() { // The Sections with -T<section> have been sorted in order of ascending // address. We must lower StartAddr if the lowest -T<section address> as // calls to setDot() must be monotonically increasing. - for (auto& KV : Config->SectionStartMap) + for (auto &KV : Config->SectionStartMap) StartAddr = std::min(StartAddr, KV.second); Commands.push_back(make<SymbolAssignment>( @@ -739,7 +752,7 @@ void LinkerScript::adjustSectionsAfterSorting() { Cmd->MemRegion = findMemoryRegion(Cmd); // Handle align (e.g. ".foo : ALIGN(16) { ... }"). if (Cmd->AlignExpr) - Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue()); + Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue()); } } @@ -1071,7 +1084,7 @@ template <class ELFT> void OutputSectionCommand::finalize() { } if ((Sec->Flags & SHF_LINK_ORDER)) { - std::sort(Sections.begin(), Sections.end(), compareByFilePosition); + std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); for (int I = 0, N = Sections.size(); I < N; ++I) *ScriptSections[I] = Sections[I]; diff --git a/ELF/MapFile.cpp b/ELF/MapFile.cpp index e0c7d8cd8b1b..2b2a95c47cf9 100644 --- a/ELF/MapFile.cpp +++ b/ELF/MapFile.cpp @@ -55,7 +55,7 @@ template <class ELFT> std::vector<DefinedRegular *> getSymbols() { for (SymbolBody *B : File->getSymbols()) if (B->File == File && !B->isSection()) if (auto *Sym = dyn_cast<DefinedRegular>(B)) - if (Sym->Section) + if (Sym->Section && Sym->Section->Live) V.push_back(Sym); return V; } diff --git a/ELF/MapFile.h b/ELF/MapFile.h index 68d8ba8d4a04..460848ff24d3 100644 --- a/ELF/MapFile.h +++ b/ELF/MapFile.h @@ -17,7 +17,7 @@ namespace elf { struct OutputSectionCommand; template <class ELFT> void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script); -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/Memory.h b/ELF/Memory.h index e5a04ed1e5a8..4000f2f9f1c9 100644 --- a/ELF/Memory.h +++ b/ELF/Memory.h @@ -61,7 +61,7 @@ inline void freeArena() { Alloc->reset(); BAlloc.Reset(); } -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/Options.td b/ELF/Options.td index 29e14c530c6a..9c78608118cc 100644 --- a/ELF/Options.td +++ b/ELF/Options.td @@ -104,6 +104,8 @@ def export_dynamic_symbol: S<"export-dynamic-symbol">, def fatal_warnings: F<"fatal-warnings">, HelpText<"Treat warnings as errors">; +def filter: J<"filter=">, HelpText<"Set DT_FILTER field to the specified name">; + def fini: S<"fini">, MetaVarName<"<symbol>">, HelpText<"Specify a finalizer function">; @@ -305,6 +307,7 @@ def alias_exclude_libs: J<"exclude-libs=">, Alias<exclude_libs>; def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>; def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">, Alias<export_dynamic_symbol>; +def alias_filter: Separate<["-"], "F">, Alias<filter>; def alias_fini_fini: J<"fini=">, Alias<fini>; def alias_format_b: S<"b">, Alias<format>; def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>; @@ -339,6 +342,7 @@ def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>; def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>; def alias_undefined_eq: J<"undefined=">, Alias<undefined>; def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>; +def alias_version_script_eq: J<"version-script=">, Alias<version_script>; def alias_version_V: Flag<["-"], "V">, Alias<version>; def alias_wrap_wrap: J<"wrap=">, Alias<wrap>; @@ -406,6 +410,3 @@ def EL : F<"EL">; def G: JoinedOrSeparate<["-"], "G">; def Qy : F<"Qy">; -// Aliases for ignored options -def alias_version_script_version_script: J<"version-script=">, - Alias<version_script>; diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index d6ae5dcae167..abe548165866 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -222,16 +222,16 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS, if (Sec) { if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags)) - error("incompatible section flags for " + Sec->Name + - "\n>>> " + toString(IS) + ": 0x" + utohexstr(IS->Flags) + + error("incompatible section flags for " + Sec->Name + "\n>>> " + + toString(IS) + ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Sec->Name + ": 0x" + utohexstr(Sec->Flags)); if (Sec->Type != IS->Type) { if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type)) Sec->Type = SHT_PROGBITS; else - error("section type mismatch for " + IS->Name + - "\n>>> " + toString(IS) + ": " + + error("section type mismatch for " + IS->Name + "\n>>> " + + toString(IS) + ": " + getELFSectionTypeName(Config->EMachine, IS->Type) + "\n>>> output section " + Sec->Name + ": " + getELFSectionTypeName(Config->EMachine, Sec->Type)); diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h index 68ee066a13da..68b46ebf6a7b 100644 --- a/ELF/OutputSections.h +++ b/ELF/OutputSections.h @@ -111,8 +111,8 @@ struct SectionKey { uint64_t Flags; uint32_t Alignment; }; -} -} +} // namespace elf +} // namespace lld namespace llvm { template <> struct DenseMapInfo<lld::elf::SectionKey> { static lld::elf::SectionKey getEmptyKey(); @@ -121,7 +121,7 @@ template <> struct DenseMapInfo<lld::elf::SectionKey> { static bool isEqual(const lld::elf::SectionKey &LHS, const lld::elf::SectionKey &RHS); }; -} +} // namespace llvm namespace lld { namespace elf { @@ -150,5 +150,4 @@ extern std::vector<OutputSectionCommand *> OutputSectionCommands; } // namespace elf } // namespace lld - #endif diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 52dbe4b583d0..e5fcb2dcc582 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -276,7 +276,7 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C, } else { C.Relocations.push_back( {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, - Offset, Addend, &Body}); + Offset, Addend, &Body}); } return Target->TlsGdRelaxSkip; } @@ -1000,16 +1000,20 @@ void ThunkCreator::mergeThunks() { } } -ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS, +static uint32_t findEndOfFirstNonExec(OutputSectionCommand &Cmd) { + for (BaseCommand *Base : Cmd.Commands) + if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) + for (auto *IS : ISD->Sections) + if ((IS->Flags & SHF_EXECINSTR) == 0) + return IS->OutSecOff + IS->getSize(); + return 0; +} + +ThunkSection *ThunkCreator::getOSThunkSec(OutputSectionCommand *Cmd, std::vector<InputSection *> *ISR) { if (CurTS == nullptr) { - uint32_t Off = 0; - for (auto *IS : OS->Sections) { - Off = IS->OutSecOff + IS->getSize(); - if ((IS->Flags & SHF_EXECINSTR) == 0) - break; - } - CurTS = addThunkSection(OS, ISR, Off); + uint32_t Off = findEndOfFirstNonExec(*Cmd); + CurTS = addThunkSection(Cmd->Sec, ISR, Off); } return CurTS; } @@ -1024,7 +1028,7 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) { OutputSectionCommand *C = Script->getCmd(TOS); std::vector<InputSection *> *Range = nullptr; for (BaseCommand *BC : C->Commands) - if (auto *ISD = dyn_cast<InputSectionDescription> (BC)) { + if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { InputSection *first = ISD->Sections.front(); InputSection *last = ISD->Sections.back(); if (IS->OutSecOff >= first->OutSecOff && @@ -1046,7 +1050,6 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, return TS; } - std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body, uint32_t Type) { auto Res = ThunkedSymbols.insert({&Body, std::vector<Thunk *>()}); @@ -1066,7 +1069,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body, // InputSectionDescription::Sections. void ThunkCreator::forEachExecInputSection( ArrayRef<OutputSectionCommand *> OutputSections, - std::function<void(OutputSection *, std::vector<InputSection *> *, + std::function<void(OutputSectionCommand *, std::vector<InputSection *> *, InputSection *)> Fn) { for (OutputSectionCommand *Cmd : OutputSections) { @@ -1077,7 +1080,7 @@ void ThunkCreator::forEachExecInputSection( if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { CurTS = nullptr; for (InputSection *IS : ISD->Sections) - Fn(OS, &ISD->Sections, IS); + Fn(Cmd, &ISD->Sections, IS); } } } @@ -1103,32 +1106,32 @@ bool ThunkCreator::createThunks( // We separate the creation of ThunkSections from the insertion of the // ThunkSections back into the OutputSection as ThunkSections are not always // inserted into the same OutputSection as the caller. - forEachExecInputSection( - OutputSections, [&](OutputSection *OS, std::vector<InputSection*> *ISR, - InputSection *IS) { - for (Relocation &Rel : IS->Relocations) { - SymbolBody &Body = *Rel.Sym; - if (Thunks.find(&Body) != Thunks.end() || - !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) - continue; - Thunk *T; - bool IsNew; - std::tie(T, IsNew) = getThunk(Body, Rel.Type); - if (IsNew) { - // Find or create a ThunkSection for the new Thunk - ThunkSection *TS; - if (auto *TIS = T->getTargetInputSection()) - TS = getISThunkSec(TIS, OS); - else - TS = getOSThunkSec(OS, ISR); - TS->addThunk(T); - Thunks[T->ThunkSym] = T; - } - // Redirect relocation to Thunk, we never go via the PLT to a Thunk - Rel.Sym = T->ThunkSym; - Rel.Expr = fromPlt(Rel.Expr); - } - }); + forEachExecInputSection(OutputSections, [&](OutputSectionCommand *Cmd, + std::vector<InputSection *> *ISR, + InputSection *IS) { + for (Relocation &Rel : IS->Relocations) { + SymbolBody &Body = *Rel.Sym; + if (Thunks.find(&Body) != Thunks.end() || + !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body)) + continue; + Thunk *T; + bool IsNew; + std::tie(T, IsNew) = getThunk(Body, Rel.Type); + if (IsNew) { + // Find or create a ThunkSection for the new Thunk + ThunkSection *TS; + if (auto *TIS = T->getTargetInputSection()) + TS = getISThunkSec(TIS, Cmd->Sec); + else + TS = getOSThunkSec(Cmd, ISR); + TS->addThunk(T); + Thunks[T->ThunkSym] = T; + } + // Redirect relocation to Thunk, we never go via the PLT to a Thunk + Rel.Sym = T->ThunkSym; + Rel.Expr = fromPlt(Rel.Expr); + } + }); // Merge all created synthetic ThunkSections back into OutputSection mergeThunks(); ++Pass; diff --git a/ELF/Relocations.h b/ELF/Relocations.h index fc3e3444ac24..ea046d248474 100644 --- a/ELF/Relocations.h +++ b/ELF/Relocations.h @@ -103,7 +103,8 @@ struct RelExprMaskBuilder<Head, Tail...> { // RelExpr's as a constant bit mask and test for membership with a // couple cheap bitwise operations. template <RelExpr... Exprs> bool isRelExprOneOf(RelExpr Expr) { - assert(0 <= Expr && (int)Expr < 64 && "RelExpr is too large for 64-bit mask!"); + assert(0 <= Expr && (int)Expr < 64 && + "RelExpr is too large for 64-bit mask!"); return (uint64_t(1) << Expr) & RelExprMaskBuilder<Exprs...>::build(); } @@ -133,12 +134,12 @@ public: private: void mergeThunks(); - ThunkSection *getOSThunkSec(OutputSection *OS, + ThunkSection *getOSThunkSec(OutputSectionCommand *Cmd, std::vector<InputSection *> *ISR); ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS); void forEachExecInputSection( ArrayRef<OutputSectionCommand *> OutputSections, - std::function<void(OutputSection *, std::vector<InputSection *> *, + std::function<void(OutputSectionCommand *, std::vector<InputSection *> *, InputSection *)> Fn); std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type); @@ -178,7 +179,7 @@ template <class ELFT> static inline int64_t getAddend(const typename ELFT::Rela &Rel) { return Rel.r_addend; } -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp index 72940ca0cfd4..b3847081697c 100644 --- a/ELF/ScriptParser.cpp +++ b/ELF/ScriptParser.cpp @@ -113,6 +113,12 @@ private: }; } // namespace +static StringRef unquote(StringRef S) { + if (S.startswith("\"")) + return S.substr(1, S.size() - 2); + return S; +} + static bool isUnderSysroot(StringRef Path) { if (Config->Sysroot == "") return false; @@ -1103,6 +1109,10 @@ void ScriptParser::readVersionDeclaration(StringRef VerStr) { expect(";"); } +static bool hasWildcard(StringRef S) { + return S.find_first_of("?*[") != StringRef::npos; +} + // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };". std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>> ScriptParser::readSymbols() { diff --git a/ELF/Strings.cpp b/ELF/Strings.cpp index 2e88bfba0fc1..bca86384002d 100644 --- a/ELF/Strings.cpp +++ b/ELF/Strings.cpp @@ -38,29 +38,6 @@ bool StringMatcher::match(StringRef S) const { return false; } -// If an input string is in the form of "foo.N" where N is a number, -// return N. Otherwise, returns 65536, which is one greater than the -// lowest priority. -int elf::getPriority(StringRef S) { - size_t Pos = S.rfind('.'); - if (Pos == StringRef::npos) - return 65536; - int V; - if (!to_integer(S.substr(Pos + 1), V, 10)) - return 65536; - return V; -} - -bool elf::hasWildcard(StringRef S) { - return S.find_first_of("?*[") != StringRef::npos; -} - -StringRef elf::unquote(StringRef S) { - if (!S.startswith("\"")) - return S; - return S.substr(1, S.size() - 2); -} - // Converts a hex string (e.g. "deadbeef") to a vector. std::vector<uint8_t> elf::parseHex(StringRef S) { std::vector<uint8_t> Hex; diff --git a/ELF/Strings.h b/ELF/Strings.h index fd1aa40539d2..68ccafa2ff17 100644 --- a/ELF/Strings.h +++ b/ELF/Strings.h @@ -21,11 +21,8 @@ namespace lld { namespace elf { -int getPriority(StringRef S); -bool hasWildcard(StringRef S); std::vector<uint8_t> parseHex(StringRef S); bool isValidCIdentifier(StringRef S); -StringRef unquote(StringRef S); // This is a lazy version of StringRef. String size is computed lazily // when it is needed. It is more efficient than StringRef to instantiate @@ -76,7 +73,7 @@ llvm::Optional<std::string> demangle(StringRef Name); inline ArrayRef<uint8_t> toArrayRef(StringRef S) { return {(const uint8_t *)S.data(), S.size()}; } -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index c802d74b8ff8..83091057ebed 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -172,8 +172,8 @@ template <class ELFT> void SymbolTable<ELFT>::addSymbolWrap(StringRef Name) { } // Creates alias for symbol. Used to implement --defsym=ALIAS=SYM. -template <class ELFT> void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, - StringRef Name) { +template <class ELFT> +void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, StringRef Name) { SymbolBody *B = find(Name); if (!B) { error("-defsym: undefined symbol: " + Name); @@ -211,13 +211,6 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { // Find an existing symbol or create and insert a new one. template <class ELFT> std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) { - // <name>@@<version> means the symbol is the default version. In that - // case symbol <name> must exist and <name>@@<version> will be used to - // resolve references to <name>. - size_t Pos = Name.find("@@"); - if (Pos != StringRef::npos) - Name = Name.take_front(Pos); - auto P = Symtab.insert( {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)}); SymIndex &V = P.first->second; @@ -400,9 +393,8 @@ static void warnOrError(const Twine &Msg) { } static void reportDuplicate(SymbolBody *Sym, InputFile *NewFile) { - warnOrError("duplicate symbol: " + toString(*Sym) + - "\n>>> defined in " + toString(Sym->File) + - "\n>>> defined in " + toString(NewFile)); + warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + + toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); } template <class ELFT> @@ -680,7 +672,8 @@ template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() { // Set symbol versions to symbols. This function handles patterns // containing no wildcard characters. template <class ELFT> -void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, uint16_t VersionId, +void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, + uint16_t VersionId, StringRef VersionName) { if (Ver.HasWildcard) return; @@ -724,13 +717,35 @@ void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver, B->symbol()->VersionId = VersionId; } +static bool isDefaultVersion(SymbolBody *B) { + return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos; +} + // This function processes version scripts by updating VersionId // member of symbols. template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { + // Symbol themselves might know their versions because symbols + // can contain versions in the form of <name>@<version>. + // Let them parse and update their names to exclude version suffix. + for (Symbol *Sym : SymVector) { + SymbolBody *Body = Sym->body(); + bool IsDefault = isDefaultVersion(Body); + Body->parseSymbolVersion(); + + if (!IsDefault) + continue; + + // <name>@@<version> means the symbol is the default version. If that's the + // case, the symbol is not used only to resolve <name> of version <version> + // but also undefined unversioned symbols with name <name>. + SymbolBody *S = find(Body->getName()); + if (S && S->isUndefined()) + S->copy(Body); + } + // Handle edge cases first. handleAnonymousVersion(); - // Now we have version definitions, so we need to set version ids to symbols. // Each version definition has a glob pattern, and all symbols that match // with the pattern get that version. diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp index 1d17f57f0c30..c69007e781a6 100644 --- a/ELF/Symbols.cpp +++ b/ELF/Symbols.cpp @@ -94,7 +94,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) { if (D.isTls() && !Config->Relocatable) { if (!Out::TlsPhdr) fatal(toString(D.File) + - " has a STT_TLS symbol but doesn't have a PT_TLS section"); + " has an STT_TLS symbol but doesn't have an SHF_TLS section"); return VA - Out::TlsPhdr->p_vaddr; } return VA; diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index fd724fac327c..4bbec4ab34bd 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -662,7 +662,12 @@ bool GotSection::empty() const { return NumEntries == 0 && !HasGotOffRel; } -void GotSection::writeTo(uint8_t *Buf) { relocateAlloc(Buf, Buf + Size); } +void GotSection::writeTo(uint8_t *Buf) { + // Buf points to the start of this section's buffer, + // whereas InputSectionBase::relocateAlloc() expects its argument + // to point to the start of the output section. + relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size); +} MipsGotSection::MipsGotSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16, @@ -812,9 +817,7 @@ unsigned MipsGotSection::getLocalEntriesNum() const { LocalEntries32.size(); } -void MipsGotSection::finalizeContents() { - updateAllocSize(); -} +void MipsGotSection::finalizeContents() { updateAllocSize(); } void MipsGotSection::updateAllocSize() { PageEntriesNum = 0; @@ -838,9 +841,7 @@ bool MipsGotSection::empty() const { return Config->Relocatable; } -uint64_t MipsGotSection::getGp() const { - return ElfSym::MipsGp->getVA(0); -} +uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); } static uint64_t readUint(uint8_t *Buf) { if (Config->Is64) @@ -1019,6 +1020,8 @@ DynamicSection<ELFT>::DynamicSection() template <class ELFT> void DynamicSection<ELFT>::addEntries() { // Add strings to .dynstr early so that .dynstr's size will be // fixed early. + for (StringRef S : Config->FilterList) + add({DT_FILTER, InX::DynStrTab->addString(S)}); for (StringRef S : Config->AuxiliaryList) add({DT_AUXILIARY, InX::DynStrTab->addString(S)}); if (!Config->Rpath.empty()) @@ -1607,7 +1610,7 @@ HashTableSection<ELFT>::HashTableSection() template <class ELFT> void HashTableSection<ELFT>::finalizeContents() { getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; - unsigned NumEntries = 2; // nbucket and nchain. + unsigned NumEntries = 2; // nbucket and nchain. NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries. // Create as many buckets as there are symbols. @@ -1926,9 +1929,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { StringPool.write(Buf); } -bool GdbIndexSection::empty() const { - return !Out::DebugInfo; -} +bool GdbIndexSection::empty() const { return !Out::DebugInfo; } template <class ELFT> EhFrameHeader<ELFT>::EhFrameHeader() @@ -2211,9 +2212,7 @@ void MergeSyntheticSection::finalizeContents() { finalizeNoTailMerge(); } -size_t MergeSyntheticSection::getSize() const { - return Builder.getSize(); -} +size_t MergeSyntheticSection::getSize() const { return Builder.getSize(); } // This function decompresses compressed sections and scans over the input // sections to create mergeable synthetic sections. It removes @@ -2312,7 +2311,7 @@ ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off) } void ThunkSection::addThunk(Thunk *T) { - uint64_t Off = alignTo(Size, T->alignment); + uint64_t Off = alignTo(Size, T->Alignment); T->Offset = Off; Thunks.push_back(T); T->addSymbols(*this); diff --git a/ELF/Target.cpp b/ELF/Target.cpp index c886419971bc..11986efc746f 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -128,6 +128,11 @@ bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType, return false; } +bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src, + uint64_t Dst) const { + return true; +} + void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const { writeGotPlt(Buf, S); } diff --git a/ELF/Target.h b/ELF/Target.h index 5914d9bbb7ef..1658a81c9b71 100644 --- a/ELF/Target.h +++ b/ELF/Target.h @@ -51,6 +51,9 @@ public: // targeting S. virtual bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, const SymbolBody &S) const; + // Return true if we can reach Dst from Src with Relocation RelocType + virtual bool inBranchRange(uint32_t RelocType, uint64_t Src, + uint64_t Dst) const; virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const = 0; virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0; @@ -154,6 +157,6 @@ static void checkAlignment(uint8_t *Loc, uint64_t V, uint32_t Type) { lld::toString(Type)); } } // namespace elf -} +} // namespace lld #endif diff --git a/ELF/Threads.h b/ELF/Threads.h index e01afd4d3fc9..9feb8683976c 100644 --- a/ELF/Threads.h +++ b/ELF/Threads.h @@ -82,7 +82,7 @@ inline void parallelForEachN(size_t Begin, size_t End, else for_each_n(llvm::parallel::seq, Begin, End, Fn); } -} -} +} // namespace elf +} // namespace lld #endif diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp index cae31027e557..07289d0efdf1 100644 --- a/ELF/Thunks.cpp +++ b/ELF/Thunks.cpp @@ -72,9 +72,7 @@ public: class ThumbV7ABSLongThunk final : public Thunk { public: - ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) { - alignment = 2; - } + ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; } uint32_t size() const override { return 10; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -84,9 +82,7 @@ public: class ThumbV7PILongThunk final : public Thunk { public: - ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) { - alignment = 2; - } + ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; } uint32_t size() const override { return 12; } void writeTo(uint8_t *Buf, ThunkSection &IS) const override; @@ -218,10 +214,10 @@ bool ThumbV7PILongThunk::isCompatibleWith(uint32_t RelocType) const { // Write MIPS LA25 thunk code to call PIC function from the non-PIC one. void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const { uint64_t S = Destination.getVA(); - write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func) + write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func) write32(Buf + 4, 0x08000000 | (S >> 2), Config->Endianness); // j func - write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func) - write32(Buf + 12, 0x00000000, Config->Endianness); // nop + write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func) + write32(Buf + 12, 0x00000000, Config->Endianness); // nop Target->relocateOne(Buf, R_MIPS_HI16, S); Target->relocateOne(Buf + 8, R_MIPS_LO16, S); } @@ -262,9 +258,7 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) { fatal("unrecognized relocation type"); } -static Thunk *addThunkMips(SymbolBody &S) { - return make<MipsThunk>(S); -} +static Thunk *addThunkMips(SymbolBody &S) { return make<MipsThunk>(S); } Thunk *addThunk(uint32_t RelocType, SymbolBody &S) { if (Config->EMachine == EM_ARM) diff --git a/ELF/Thunks.h b/ELF/Thunks.h index 00b6b2cf2994..21eba699fe4f 100644 --- a/ELF/Thunks.h +++ b/ELF/Thunks.h @@ -50,7 +50,7 @@ public: const SymbolBody &Destination; SymbolBody *ThunkSym; uint64_t Offset; - uint32_t alignment = 4; + uint32_t Alignment = 4; }; // For a Relocation to symbol S create a Thunk to be added to a synthetic diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index bf43ee5c5f91..1853f99bc600 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -257,7 +257,6 @@ template <class ELFT> void Writer<ELFT>::run() { if (ErrorCount) return; - // Handle -Map option. writeMapFile<ELFT>(OutputSectionCommands); if (ErrorCount) @@ -1331,7 +1330,7 @@ template <class ELFT> void Writer<ELFT>::addPredefinedSections() { // ARM ABI requires .ARM.exidx to be terminated by some piece of data. // We have the terminater synthetic section class. Add that at the end. OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx"); - if (!Cmd || Cmd->Commands.empty() || Config->Relocatable) + if (!Cmd || !Cmd->Sec || Config->Relocatable) return; auto *Sentinel = make<ARMExidxSentinelSection>(); @@ -1392,7 +1391,8 @@ OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) { return nullptr; } -template <class ELFT> OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) { +template <class ELFT> +OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) { if (OutputSectionCommand *Cmd = findSectionCommand(Name)) return Cmd->Sec; return nullptr; diff --git a/ELF/Writer.h b/ELF/Writer.h index e935b6419de6..7fa56bea1c35 100644 --- a/ELF/Writer.h +++ b/ELF/Writer.h @@ -55,7 +55,7 @@ uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, llvm::StringRef FileName); bool isMipsN32Abi(const InputFile *F); -} -} +} // namespace elf +} // namespace lld #endif diff --git a/docs/windows_support.rst b/docs/windows_support.rst index 56df45b32633..6b06d29afafd 100644 --- a/docs/windows_support.rst +++ b/docs/windows_support.rst @@ -29,8 +29,6 @@ Development status Driver :good:`Mostly done`. Some exotic command line options that are not usually used for application develompent, such as ``/DRIVER``, are not supported. - Options for Windows 8 app store are not recognized too - (e.g. ``/APPCONTAINER``). Linking against DLL :good:`Done`. LLD can read import libraries needed to link against DLL. Both @@ -44,8 +42,7 @@ Creating DLL :good:`Done`. LLD creates a DLL if ``/DLL`` option is given. Exported functions can be specified either via command line (``/EXPORT``) or via module-definition file (.def). Both export-by-name and export-by-ordinal are - supported. LLD uses Microsoft ``lib.exe`` tool to create an import library - file. + supported. Windows resource files support :good:`Done`. If an ``.res`` file is given, LLD converts the file to a COFF diff --git a/test/COFF/Inputs/default.def b/test/COFF/Inputs/default.def new file mode 100644 index 000000000000..1d59beebbb26 --- /dev/null +++ b/test/COFF/Inputs/default.def @@ -0,0 +1,2 @@ +EXPORTS + f diff --git a/test/COFF/Inputs/extension.def b/test/COFF/Inputs/extension.def new file mode 100644 index 000000000000..d93f0dc1ecce --- /dev/null +++ b/test/COFF/Inputs/extension.def @@ -0,0 +1,3 @@ +LIBRARY library.ext +EXPORTS + f diff --git a/test/COFF/Inputs/named.def b/test/COFF/Inputs/named.def new file mode 100644 index 000000000000..07c8622189db --- /dev/null +++ b/test/COFF/Inputs/named.def @@ -0,0 +1,3 @@ +LIBRARY library +EXPORTS + f diff --git a/test/COFF/Inputs/object.s b/test/COFF/Inputs/object.s new file mode 100644 index 000000000000..b70599385591 --- /dev/null +++ b/test/COFF/Inputs/object.s @@ -0,0 +1,13 @@ + + .text + + .def f + .scl 2 + .type 32 + .endef + .global f +f: + retq $0 + + .section .drectve,"rd" + .ascii " /EXPORT:f" diff --git a/test/COFF/Inputs/pdb-type-server-simple-a.yaml b/test/COFF/Inputs/pdb-type-server-simple-a.yaml new file mode 100644 index 000000000000..78c68168127b --- /dev/null +++ b/test/COFF/Inputs/pdb-type-server-simple-a.yaml @@ -0,0 +1,255 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .drectve + Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] + Alignment: 1 + SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220 + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_OBJNAME + ObjNameSym: + Signature: 0 + ObjectName: 'C:\src\llvm-project\build\a.obj' + - Kind: S_COMPILE3 + Compile3Sym: + Flags: [ SecurityChecks, HotPatch ] + Machine: X64 + FrontendMajor: 19 + FrontendMinor: 0 + FrontendBuild: 24215 + FrontendQFE: 1 + BackendMajor: 19 + BackendMinor: 0 + BackendBuild: 24215 + BackendQFE: 1 + Version: 'Microsoft (R) Optimizing Compiler' + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 27 + DbgStart: 4 + DbgEnd: 22 + FunctionType: 4098 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 56 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_REGREL32 + RegRelativeSym: + Offset: 32 + Type: 4102 + Register: RSP + VarName: f + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 27 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\a.c' + Lines: + - Offset: 0 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 4 + LineStart: 4 + IsStatement: true + EndDelta: 0 + - Offset: 12 + LineStart: 5 + IsStatement: true + EndDelta: 0 + - Offset: 22 + LineStart: 6 + IsStatement: true + EndDelta: 0 + Columns: + - !Symbols + Records: + - Kind: S_UDT + UDTSym: + Type: 4102 + UDTName: Foo + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\a.c' + Kind: MD5 + Checksum: BF69E7E933074E1B7ED1FE8FB395965B + - !StringTable + Strings: + - 'c:\src\llvm-project\build\a.c' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4107 + Relocations: + - VirtualAddress: 152 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 156 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 224 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 228 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - Name: '.debug$T' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Types: + - Kind: LF_TYPESERVER2 + TypeServer2: + Guid: '{41414141-4141-4141-4141-414141414141}' + Age: 1 + Name: 'C:\src\llvm-project\build\ts.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC38C74424202A000000488D4C2420E8000000004883C438C3 + Relocations: + - VirtualAddress: 18 + SymbolName: g + Type: IMAGE_REL_AMD64_REL32 + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004620000' + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 000000001B00000000000000 + Relocations: + - VirtualAddress: 0 + SymbolName: '$LN3' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 4 + SymbolName: '$LN3' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 8 + SymbolName: '$unwind$main' + Type: IMAGE_REL_AMD64_ADDR32NB +symbols: + - Name: .drectve + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 47 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$S' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 388 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$T' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 64 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 27 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 1939996292 + Number: 0 + - Name: g + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: main + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '$LN3' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_LABEL + - Name: .xdata + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 931692337 + Number: 0 + - Name: '$unwind$main' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .pdata + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 567356797 + Number: 0 + - Name: '$pdata$main' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC +... diff --git a/test/COFF/Inputs/pdb-type-server-simple-b.yaml b/test/COFF/Inputs/pdb-type-server-simple-b.yaml new file mode 100644 index 000000000000..56e97d530894 --- /dev/null +++ b/test/COFF/Inputs/pdb-type-server-simple-b.yaml @@ -0,0 +1,173 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: .drectve + Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] + Alignment: 1 + SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220 + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_OBJNAME + ObjNameSym: + Signature: 0 + ObjectName: 'C:\src\llvm-project\build\b.obj' + - Kind: S_COMPILE3 + Compile3Sym: + Flags: [ SecurityChecks, HotPatch ] + Machine: X64 + FrontendMajor: 19 + FrontendMinor: 0 + FrontendBuild: 24215 + FrontendQFE: 1 + BackendMajor: 19 + BackendMinor: 0 + BackendBuild: 24215 + BackendQFE: 1 + Version: 'Microsoft (R) Optimizing Compiler' + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 13 + DbgStart: 5 + DbgEnd: 12 + FunctionType: 4099 + Flags: [ ] + DisplayName: g + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_REGREL32 + RegRelativeSym: + Offset: 8 + Type: 4097 + Register: RSP + VarName: p + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 13 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\b.c' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + Columns: + - !Symbols + Records: + - Kind: S_UDT + UDTSym: + Type: 4102 + UDTName: Foo + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\b.c' + Kind: MD5 + Checksum: DDF8FD35CD67990C5D4147516BE10D0C + - !StringTable + Strings: + - 'c:\src\llvm-project\build\b.c' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4111 + Relocations: + - VirtualAddress: 152 + SymbolName: g + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 156 + SymbolName: g + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 220 + SymbolName: g + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 224 + SymbolName: g + Type: IMAGE_REL_AMD64_SECTION + - Name: '.debug$T' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Types: + - Kind: LF_TYPESERVER2 + TypeServer2: + Guid: '{41414141-4141-4141-4141-414141414141}' + Age: 1 + Name: 'C:\src\llvm-project\build\ts.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 48894C2408488B4424088B00C3 +symbols: + - Name: .drectve + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 47 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$S' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 360 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$T' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 64 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 13 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3246683207 + Number: 0 + - Name: g + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/Inputs/pdb-type-server-simple-ts.yaml b/test/COFF/Inputs/pdb-type-server-simple-ts.yaml new file mode 100644 index 000000000000..73496571ac72 --- /dev/null +++ b/test/COFF/Inputs/pdb-type-server-simple-ts.yaml @@ -0,0 +1,147 @@ +--- +MSF: + SuperBlock: + BlockSize: 4096 + FreeBlockMap: 1 + NumBlocks: 19 + NumDirectoryBytes: 64 + Unknown1: 0 + BlockMapAddr: 17 + NumDirectoryBlocks: 1 + DirectoryBlocks: [ 16 ] + NumStreams: 0 + FileSize: 77824 +PdbStream: + Age: 1 + Guid: '{41414141-4141-4141-4141-414141414141}' + Signature: 1500053944 + Features: [ VC140 ] + Version: VC70 +TpiStream: + Version: VC80 + Records: + - Kind: LF_STRUCTURE + Class: + MemberCount: 0 + Options: [ None, ForwardReference, HasUniqueName ] + FieldList: 0 + Name: Foo + UniqueName: '.?AUFoo@@' + DerivationList: 0 + VTableShape: 0 + Size: 0 + - Kind: LF_POINTER + Pointer: + ReferentType: 4096 + Attrs: 65548 + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ 4097 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 1 + ArgumentList: 4098 + - Kind: LF_POINTER + Pointer: + ReferentType: 4099 + Attrs: 65548 + - Kind: LF_FIELDLIST + FieldList: + - Kind: LF_MEMBER + DataMember: + Attrs: 3 + Type: 116 + FieldOffset: 0 + Name: x + - Kind: LF_STRUCTURE + Class: + MemberCount: 1 + Options: [ None, HasUniqueName ] + FieldList: 4101 + Name: Foo + UniqueName: '.?AUFoo@@' + DerivationList: 0 + VTableShape: 0 + Size: 4 + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ 0 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4103 +IpiStream: + Version: VC80 + Records: + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'c:\src\llvm-project\build\a.c' + - Kind: LF_UDT_SRC_LINE + UdtSourceLine: + UDT: 4102 + SourceFile: 4096 + LineNumber: 1 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4104 + Name: main + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4099 + Name: g + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: '-c -Zi -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um' + - Kind: LF_SUBSTR_LIST + StringList: + StringIndices: [ 4102 ] + - Kind: LF_STRING_ID + StringId: + Id: 4103 + String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: a.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build\ts.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4100, 4101, 4105, 4106, 4104 ] + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'c:\src\llvm-project\build\b.c' + - Kind: LF_UDT_SRC_LINE + UdtSourceLine: + UDT: 4102 + SourceFile: 4108 + LineNumber: 1 + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: b.c + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4100, 4101, 4110, 4106, 4104 ] +... diff --git a/test/COFF/common.test b/test/COFF/common.test index 007cfcfb6f92..4a00153f3e93 100644 --- a/test/COFF/common.test +++ b/test/COFF/common.test @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: yaml2obj %s > %t.obj # RUN: lld-link /out:%t.exe /entry:main %t.obj %t.obj # RUN: llvm-objdump -d %t.exe | FileCheck %s diff --git a/test/COFF/conflict.test b/test/COFF/conflict.test index a634c7185675..ae8e6c8ad327 100644 --- a/test/COFF/conflict.test +++ b/test/COFF/conflict.test @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: yaml2obj < %s > %t1.obj # RUN: yaml2obj < %s > %t2.obj # RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log diff --git a/test/COFF/constant.test b/test/COFF/constant.test index 3c8956beac9c..02d6b3e2ccae 100644 --- a/test/COFF/constant.test +++ b/test/COFF/constant.test @@ -1,3 +1,4 @@ +REQUIRES: x86 RUN: mkdir -p %t RUN: llvm-mc -triple i686-unknown-windows-msvc -filetype obj -o %t/import.o %S/Inputs/constant-import.s RUN: llc -mtriple i686-unknown-windows-msvc -filetype obj -o %t/export.o %S/Inputs/constant-export.ll diff --git a/test/COFF/def-export-stdcall.s b/test/COFF/def-export-stdcall.s index cdca7ae76acf..d7700d9e9535 100644 --- a/test/COFF/def-export-stdcall.s +++ b/test/COFF/def-export-stdcall.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj # RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall" > %t.def # RUN: lld-link -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib diff --git a/test/COFF/delayimports32.test b/test/COFF/delayimports32.test index 9c4fcae5b6a5..53aadbb6a185 100644 --- a/test/COFF/delayimports32.test +++ b/test/COFF/delayimports32.test @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj # RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \ # RUN: /entry:main@0 /alternatename:___delayLoadHelper2@8=_main@0 \ diff --git a/test/COFF/entry-mangled.test b/test/COFF/entry-mangled.test index acf54ba07973..1140e8298fbc 100644 --- a/test/COFF/entry-mangled.test +++ b/test/COFF/entry-mangled.test @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: yaml2obj < %s > %t.obj # RUN: lld-link /out:%t.exe /entry:main %t.obj # RUN: llvm-as -o %t.lto.obj %S/Inputs/entry-mangled.ll diff --git a/test/COFF/entrylib.ll b/test/COFF/entrylib.ll index 4ffa42c44a3e..602b4ff63336 100644 --- a/test/COFF/entrylib.ll +++ b/test/COFF/entrylib.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as -o %t.obj %s ; RUN: rm -f %t.lib ; RUN: llvm-ar cru %t.lib %t.obj diff --git a/test/COFF/implib-name.test b/test/COFF/implib-name.test new file mode 100644 index 000000000000..81b5b258483f --- /dev/null +++ b/test/COFF/implib-name.test @@ -0,0 +1,71 @@ +# RUN: mkdir -p %T +# RUN: llvm-mc -triple x86_64-unknown-windows-msvc -filetype obj -o %T/object.obj %S/Inputs/object.s + +# RUN: lld-link /dll /machine:x64 /def:%S/Inputs/named.def /out:%T/library.dll %T/object.obj /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/library.lib | FileCheck %s -check-prefix CHECK-DEFAULT-DLL-EXT + +# RUN: lld-link /machine:x64 /def:%S/Inputs/named.def /out:%T/library.lib +# RUN: llvm-ar t %T/library.lib | FileCheck %s -check-prefix CHECK-DEFAULT-DLL-EXT + +CHECK-DEFAULT-DLL-EXT: library.dll +CHECK-DEFAULT-DLL-EXT: library.dll +CHECK-DEFAULT-DLL-EXT: library.dll +CHECK-DEFAULT-DLL-EXT: library.dll + +# RUN: lld-link /machine:x64 /def:%S/Inputs/named.def /out:%T/library.exe %T/object.obj /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/library.lib | FileCheck %s -check-prefix CHECK-DEFAULT-EXE-EXT + +CHECK-DEFAULT-EXE-EXT: library.exe +CHECK-DEFAULT-EXE-EXT: library.exe +CHECK-DEFAULT-EXE-EXT: library.exe +CHECK-DEFAULT-EXE-EXT: library.exe + +# RUN: lld-link /dll /machine:x64 /def:%S/Inputs/extension.def /out:%T/extension.dll /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/extension.lib | FileCheck %s -check-prefix CHECK-EXTENSION + +# RUN: lld-link /machine:x64 /def:%S/Inputs/extension.def /out:%T/extension.exe /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/extension.lib | FileCheck %s -check-prefix CHECK-EXTENSION + +# RUN: lld-link /machine:x64 /def:%S/Inputs/extension.def /out:%T/extension.lib +# RUN: llvm-ar t %T/extension.lib | FileCheck %s -check-prefix CHECK-EXTENSION + +CHECK-EXTENSION: library.ext +CHECK-EXTENSION: library.ext +CHECK-EXTENSION: library.ext +CHECK-EXTENSION: library.ext + +# RUN: lld-link /dll /machine:x64 /def:%S/Inputs/default.def /out:%T/default.dll /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-OUTPUT-NAME-DLL + +# RUN: lld-link /machine:x64 /def:%S/Inputs/default.def /out:%T/default.lib +# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-OUTPUT-NAME-DLL + +CHECK-OUTPUT-NAME-DLL: default.dll +CHECK-OUTPUT-NAME-DLL: default.dll +CHECK-OUTPUT-NAME-DLL: default.dll +CHECK-OUTPUT-NAME-DLL: default.dll + +# RUN: lld-link /machine:x64 /def:%S/Inputs/default.def /out:%T/default.exe %T/object.obj /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-OUTPUT-NAME-EXE + +CHECK-OUTPUT-NAME-EXE: default.exe +CHECK-OUTPUT-NAME-EXE: default.exe +CHECK-OUTPUT-NAME-EXE: default.exe +CHECK-OUTPUT-NAME-EXE: default.exe + +# RUN: lld-link /machine:x64 /out:%T/default.exe %T/object.obj /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-NODEF-EXE + +CHECK-NODEF-EXE: default.exe +CHECK-NODEF-EXE: default.exe +CHECK-NODEF-EXE: default.exe +CHECK-NODEF-EXE: default.exe + +# RUN: lld-link /machine:x64 /dll /out:%T/default.dll %T/object.obj /entry:f /subsystem:CONSOLE +# RUN: llvm-ar t %T/default.lib | FileCheck %s -check-prefix CHECK-NODEF-DLL + +CHECK-NODEF-DLL: default.dll +CHECK-NODEF-DLL: default.dll +CHECK-NODEF-DLL: default.dll +CHECK-NODEF-DLL: default.dll + diff --git a/test/COFF/imports.test b/test/COFF/imports.test index 584c24eb1b76..326bfbebbb05 100644 --- a/test/COFF/imports.test +++ b/test/COFF/imports.test @@ -1,3 +1,4 @@ +# REQUIRES: x86 # Verify that the lld can handle .lib files and emit .idata sections. # # RUN: lld-link /out:%t.exe /entry:main /subsystem:console \ diff --git a/test/COFF/include-lto.ll b/test/COFF/include-lto.ll index 6ca32fa71ad1..d5ae546ab719 100644 --- a/test/COFF/include-lto.ll +++ b/test/COFF/include-lto.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as -o %t.obj %s ; RUN: lld-link /dll /out:%t.dll %t.obj ; RUN: llvm-objdump -d %t.dll | FileCheck %s diff --git a/test/COFF/msvclto-archive.ll b/test/COFF/msvclto-archive.ll index 047b19e76ddf..334565a1bef7 100644 --- a/test/COFF/msvclto-archive.ll +++ b/test/COFF/msvclto-archive.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ;; Make sure we re-create archive files to strip bitcode files. ;; Do not create empty archives because the MSVC linker diff --git a/test/COFF/msvclto-order.ll b/test/COFF/msvclto-order.ll index 8991dce4a8d5..6f569af4af0c 100644 --- a/test/COFF/msvclto-order.ll +++ b/test/COFF/msvclto-order.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: opt -thinlto-bc %s -o %t.obj ; RUN: llc -filetype=obj %S/Inputs/msvclto-order-a.ll -o %T/msvclto-order-a.obj ; RUN: llvm-ar crs %T/msvclto-order-a.lib %T/msvclto-order-a.obj diff --git a/test/COFF/msvclto.ll b/test/COFF/msvclto.ll index 7fa9c54711b4..66fabeb80c74 100644 --- a/test/COFF/msvclto.ll +++ b/test/COFF/msvclto.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as -o %t.obj %s ; RUN: mkdir -p %t.dir ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s diff --git a/test/COFF/pdb-comdat.test b/test/COFF/pdb-comdat.test index ea691aec87ad..f85dacdbf4bb 100644 --- a/test/COFF/pdb-comdat.test +++ b/test/COFF/pdb-comdat.test @@ -56,7 +56,7 @@ CHECK: flags = has async eh | opt speed CHECK: 196 | S_END [size = 4] CHECK: 200 | S_GDATA32 [size = 24] `global` CHECK: type = 0x0074 (int), addr = 0000:0000 -CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `4106` +CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100A` CHECK: 232 | S_GPROC32_ID [size = 44] `foo` CHECK: parent = 0, end = 308, addr = 0002:0032, code size = 15 CHECK: debug start = 0, debug end = 14, flags = none @@ -81,7 +81,7 @@ CHECK: flags = has async eh | opt speed CHECK: 196 | S_END [size = 4] CHECK: 200 | S_GDATA32 [size = 24] `global` CHECK: type = 0x0074 (int), addr = 0000:0000 -CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `4109` +CHECK: 224 | S_BUILDINFO [size = 8] BuildId = `0x100D` CHECK-NOT: S_GPROC32_ID {{.*}} `foo` CHECK-LABEL: Mod 0002 | `* Linker *`: diff --git a/test/COFF/pdb-lib.s b/test/COFF/pdb-lib.s index ab95f82a2a91..74d987eac814 100644 --- a/test/COFF/pdb-lib.s +++ b/test/COFF/pdb-lib.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: rm -rf %t && mkdir -p %t && cd %t # RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj # RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj diff --git a/test/COFF/pdb-symbol-types.yaml b/test/COFF/pdb-symbol-types.yaml index 8abbc365b34e..2ad6f5b07bf4 100644 --- a/test/COFF/pdb-symbol-types.yaml +++ b/test/COFF/pdb-symbol-types.yaml @@ -35,7 +35,7 @@ # CHECK: original type = 0x1004 # CHECK: 240 | S_UDT [size = 12] `Foo` # CHECK: original type = 0x1004 -# CHECK: 252 | S_BUILDINFO [size = 8] BuildId = `4106` +# CHECK: 252 | S_BUILDINFO [size = 8] BuildId = `0x100A` # CHECK-LABEL: Mod 0001 | `* Linker *`: --- !COFF diff --git a/test/COFF/pdb-type-server-missing.yaml b/test/COFF/pdb-type-server-missing.yaml new file mode 100644 index 000000000000..91bb04f5622f --- /dev/null +++ b/test/COFF/pdb-type-server-missing.yaml @@ -0,0 +1,132 @@ +# This is an object compiled with /Zi (see the LF_TYPESERVER2 record) without an +# adjacent type server PDB. Test that LLD fails gracefully on it. + +# FIXME: Ideally we'd do what MSVC does, which is to warn and drop all debug +# info in the object with the missing PDB. + +# RUN: yaml2obj %s -o %t.obj +# RUN: not lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s + +# CHECK: error: Type server PDB was not found + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 3 + DbgStart: 0 + DbgEnd: 2 + FunctionType: 4199 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 3 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\t.c' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\t.c' + Kind: MD5 + Checksum: 270A878DCC1B845655B162F56C4F5020 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\t.c' + Relocations: + - VirtualAddress: 44 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - Name: '.debug$T' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Types: + - Kind: LF_TYPESERVER2 + TypeServer2: + Guid: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' + Age: 18 + Name: 'C:\src\llvm-project\build\definitely_not_found_for_sure.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 33C0C3 +symbols: + - Name: '.debug$S' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 328 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$T' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 564 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 3 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 4021952397 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/pdb-type-server-simple.test b/test/COFF/pdb-type-server-simple.test new file mode 100644 index 000000000000..c0de4e390914 --- /dev/null +++ b/test/COFF/pdb-type-server-simple.test @@ -0,0 +1,91 @@ +Replicate this scenario: + +$ cat a.c +struct Foo { int x; }; +int g(struct Foo *p); +int main() { + struct Foo f = {42}; + return g(&f); +} + +$ cat b.c +struct Foo { int x; }; +int g(struct Foo *p) { return p->x; } + +$ cl -c a.c b.c -Zi -Fdts.pdb + +$ lld-link a.obj b.obj -debug -entry:main -nodefaultlib -out:t.exe + +RUN: rm -rf %t && mkdir -p %t && cd %t +RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj +RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj +RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb +RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib +RUN: llvm-pdbutil dump -symbols -types -ids %t/t.pdb | FileCheck %s + + +CHECK-LABEL: Types (TPI Stream) +CHECK: ============================================================ + +CHECK: [[FOO_DECL:[^ ]*]] | LF_STRUCTURE [size = 36] `Foo` + +CHECK: [[FOO_PTR:[^ ]*]] | LF_POINTER [size = 12] +CHECK-NEXT: referent = [[FOO_DECL]] + +CHECK: [[G_ARGS:[^ ]*]] | LF_ARGLIST [size = 12] +CHECK-NEXT: [[FOO_PTR]]: `Foo*` + +CHECK: [[G_PROTO:[^ ]*]] | LF_PROCEDURE [size = 16] +CHECK-NEXT: return type = 0x0074 (int), # args = 1, param list = [[G_ARGS]] +CHECK-NEXT: calling conv = cdecl, options = None + +CHECK: [[FOO_COMPLETE:[^ ]*]] | LF_STRUCTURE [size = 36] `Foo` +CHECK-NEXT: unique name: `.?AUFoo@@` +CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: 0x{{.*}} +CHECK: options: has unique name +CHECK: [[MAIN_PROTO:[^ ]*]] | LF_PROCEDURE [size = 16] +CHECK: return type = 0x0074 (int), # args = 0, param list = 0x{{.*}} +CHECK: calling conv = cdecl, options = None + + +CHECK-LABEL: Types (IPI Stream) +CHECK: ============================================================ +CHECK: [[MAIN_ID:[^ ]*]] | LF_FUNC_ID [size = 20] +CHECK: name = main, type = [[MAIN_PROTO]], parent scope = <no type> +CHECK: [[G_ID:[^ ]*]] | LF_FUNC_ID [size = 16] +CHECK: name = g, type = [[G_PROTO]], parent scope = <no type> +CHECK: [[A_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28] +CHECK: {{.*}}: `a.c` +CHECK: [[B_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28] +CHECK: {{.*}}: `b.c` + +CHECK-LABEL: Symbols +CHECK: ============================================================ +CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`: +CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\a.obj` +CHECK: 104 | S_GPROC32_ID [size = 44] `main` +CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 27 +CHECK: type = {{.*}}, debug start = 4, debug end = 22, flags = none +CHECK: 200 | S_UDT [size = 12] `Foo` +CHECK: original type = [[FOO_COMPLETE]] +CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]` +CHECK-LABEL: Mod 0001 | `{{.*}}b.obj`: +CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\b.obj` +CHECK: 44 | S_COMPILE3 [size = 60] +CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c +CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1 +CHECK: flags = security checks | hot patchable +CHECK: 104 | S_GPROC32_ID [size = 44] `g` +CHECK: parent = 0, end = 196, addr = 0002:0032, code size = 13 +CHECK: type = {{.*}}, debug start = 5, debug end = 12, flags = none +CHECK: 148 | S_FRAMEPROC [size = 32] +CHECK: size = 0, padding size = 0, offset to padding = 0 +CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 +CHECK: flags = has async eh | opt speed +CHECK: 180 | S_REGREL32 [size = 16] `p` +CHECK: type = [[FOO_PTR]] (Foo*), register = rsp, offset = 8 +CHECK: 196 | S_END [size = 4] +CHECK: 200 | S_UDT [size = 12] `Foo` +CHECK: original type = [[FOO_COMPLETE]] +CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` +CHECK-LABEL: Mod 0002 | `* Linker *`: diff --git a/test/COFF/reloc-discarded-dwarf.s b/test/COFF/reloc-discarded-dwarf.s new file mode 100644 index 000000000000..d779d2f5b8fc --- /dev/null +++ b/test/COFF/reloc-discarded-dwarf.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t1.obj %s +# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t2.obj %s + +# LLD should not error on relocations in DWARF debug sections against symbols in +# discarded sections. +# RUN: lld-link -entry:main -debug %t1.obj %t2.obj + + .section .text,"xr",discard,main + .globl main +main: +f: + retq + + .section .debug_info,"dr" + .quad f diff --git a/test/COFF/reloc-oob.yaml b/test/COFF/reloc-oob.yaml new file mode 100644 index 000000000000..0ed4c4d57976 --- /dev/null +++ b/test/COFF/reloc-oob.yaml @@ -0,0 +1,62 @@ +# Make sure LLD does some light relocation bounds checking. + +# RUN: yaml2obj %s -o %t.obj +# RUN: not lld-link %t.obj -entry:main -nodefaultlib -out:%t.exe 2>&1 | FileCheck %s + +# CHECK: error: relocation points beyond the end of its parent section + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 5589E550C745FC00000000A10000000083C4045DC3 + Relocations: + - VirtualAddress: 24 + SymbolName: _g + Type: IMAGE_REL_I386_DIR32 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: 2A000000 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 21 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 662775349 + Number: 1 + - Name: .data + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 3482275674 + Number: 2 + - Name: _main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: _g + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/savetemps.ll b/test/COFF/savetemps.ll index 4e59812441a9..7f2e11c17715 100644 --- a/test/COFF/savetemps.ll +++ b/test/COFF/savetemps.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: rm -fr %T/savetemps ; RUN: mkdir %T/savetemps ; RUN: llvm-as -o %T/savetemps/savetemps.obj %s diff --git a/test/COFF/thinlto-archives.ll b/test/COFF/thinlto-archives.ll index 7a5e36aa1fb9..9a47a3a6feb6 100644 --- a/test/COFF/thinlto-archives.ll +++ b/test/COFF/thinlto-archives.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: rm -fr %T/thinlto-archives ; RUN: mkdir %T/thinlto-archives %T/thinlto-archives/a %T/thinlto-archives/b ; RUN: opt -thinlto-bc -o %T/thinlto-archives/main.obj %s diff --git a/test/COFF/thinlto-mangled.ll b/test/COFF/thinlto-mangled.ll index efcd9c3d2d0a..8c901cbd70ba 100644 --- a/test/COFF/thinlto-mangled.ll +++ b/test/COFF/thinlto-mangled.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: opt -thinlto-bc %s -o %t.obj ; RUN: opt -thinlto-bc %S/Inputs/thinlto-mangled-qux.ll -o %T/thinlto-mangled-qux.obj ; RUN: lld-link -out:%t.exe -entry:main %t.obj %T/thinlto-mangled-qux.obj diff --git a/test/COFF/thinlto.ll b/test/COFF/thinlto.ll index 11b689d6327e..f01d0d802289 100644 --- a/test/COFF/thinlto.ll +++ b/test/COFF/thinlto.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: rm -fr %T/thinlto ; RUN: mkdir %T/thinlto ; RUN: opt -thinlto-bc -o %T/thinlto/main.obj %s diff --git a/test/ELF/Inputs/ctors_dtors_priority1.s b/test/ELF/Inputs/ctors_dtors_priority1.s index 2eb19d7edad9..2102dba278dc 100644 --- a/test/ELF/Inputs/ctors_dtors_priority1.s +++ b/test/ELF/Inputs/ctors_dtors_priority1.s @@ -1,5 +1,5 @@ .section .ctors, "aw", @progbits - .byte 0xA1 + .quad 0xA1 .section .dtors, "aw", @progbits - .byte 0xA2 + .quad 0xA2 diff --git a/test/ELF/Inputs/ctors_dtors_priority2.s b/test/ELF/Inputs/ctors_dtors_priority2.s index fb85ce87c5c5..e94b15e2b894 100644 --- a/test/ELF/Inputs/ctors_dtors_priority2.s +++ b/test/ELF/Inputs/ctors_dtors_priority2.s @@ -1,5 +1,5 @@ .section .ctors, "aw", @progbits - .byte 0xB1 + .quad 0xB1 .section .dtors, "aw", @progbits - .byte 0xB2 + .quad 0xB2 diff --git a/test/ELF/Inputs/ctors_dtors_priority3.s b/test/ELF/Inputs/ctors_dtors_priority3.s index 96418d351a85..7bba90cc70f8 100644 --- a/test/ELF/Inputs/ctors_dtors_priority3.s +++ b/test/ELF/Inputs/ctors_dtors_priority3.s @@ -1,5 +1,5 @@ .section .ctors, "aw", @progbits - .byte 0xC1 + .quad 0xC1 .section .dtors, "aw", @progbits - .byte 0xC2 + .quad 0xC2 diff --git a/test/ELF/Inputs/gdb-index-a.elf b/test/ELF/Inputs/gdb-index-a.elf Binary files differdeleted file mode 100644 index 9b90b0dc233e..000000000000 --- a/test/ELF/Inputs/gdb-index-a.elf +++ /dev/null diff --git a/test/ELF/Inputs/gdb-index-b.elf b/test/ELF/Inputs/gdb-index-b.elf Binary files differdeleted file mode 100644 index b3356d8c773b..000000000000 --- a/test/ELF/Inputs/gdb-index-b.elf +++ /dev/null diff --git a/test/ELF/Inputs/gdb-index.s b/test/ELF/Inputs/gdb-index.s new file mode 100644 index 000000000000..907a66d350b0 --- /dev/null +++ b/test/ELF/Inputs/gdb-index.s @@ -0,0 +1,73 @@ +.text +.Ltext0: +.globl main2 +.type main2, @function +main2: + nop + nop +.Letext0: + +.section .debug_info,"",@progbits +.long 0x30 +.value 0x4 +.long 0 +.byte 0x8 +.uleb128 0x1 +.quad .Ltext0 +.quad .Letext0-.Ltext0 +.long 0 +.long 0 +.long 0 +.long 0 +.byte 0x63 +.byte 0x88 +.byte 0xb4 +.byte 0x61 +.byte 0xaa +.byte 0xb6 +.byte 0xb0 +.byte 0x67 + +.section .debug_abbrev,"",@progbits +.uleb128 0x1 +.uleb128 0x11 +.byte 0 +.uleb128 0x11 +.uleb128 0x1 +.uleb128 0x12 +.uleb128 0x7 +.uleb128 0x10 +.uleb128 0x17 +.uleb128 0x2130 +.uleb128 0xe +.uleb128 0x1b +.uleb128 0xe +.uleb128 0x2134 +.uleb128 0x19 +.uleb128 0x2133 +.uleb128 0x17 +.uleb128 0x2131 +.uleb128 0x7 +.byte 0 +.byte 0 +.byte 0 + +.section .debug_gnu_pubnames,"",@progbits +.long 0x18 +.value 0x2 +.long 0 +.long 0x33 +.long 0x18 +.byte 0x30 +.string "main2" +.long 0 + +.section .debug_gnu_pubtypes,"",@progbits +.long 0x17 +.value 0x2 +.long 0 +.long 0x33 +.long 0x2b +.byte 0x90 +.string "int" +.long 0 diff --git a/test/ELF/Inputs/symver-archive1.s b/test/ELF/Inputs/symver-archive1.s deleted file mode 100644 index be7c64494215..000000000000 --- a/test/ELF/Inputs/symver-archive1.s +++ /dev/null @@ -1,6 +0,0 @@ -.text -.globl x -.type x, @function -x: - -.symver x, xx@@VER diff --git a/test/ELF/Inputs/symver-archive2.s b/test/ELF/Inputs/symver-archive2.s deleted file mode 100644 index a9b9d0b0a35b..000000000000 --- a/test/ELF/Inputs/symver-archive2.s +++ /dev/null @@ -1 +0,0 @@ -call xx@PLT diff --git a/test/ELF/allow-shlib-undefined.s b/test/ELF/allow-shlib-undefined.s index 2d068b0f60ed..abb0351db723 100644 --- a/test/ELF/allow-shlib-undefined.s +++ b/test/ELF/allow-shlib-undefined.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # --allow-shlib-undefined and --no-allow-shlib-undefined are fully # ignored in linker implementation. # --allow-shlib-undefined is set by default diff --git a/test/ELF/as-needed-no-reloc.s b/test/ELF/as-needed-no-reloc.s index 68f03d782c24..f8c34f80a595 100644 --- a/test/ELF/as-needed-no-reloc.s +++ b/test/ELF/as-needed-no-reloc.s @@ -16,7 +16,7 @@ # CHECK-NEXT: Other: 0 # CHECK-NEXT: Section: Undefined -# CHECK: NEEDED SharedLibrary ({{.*}}as-needed-no-reloc{{.*}}2.so) +# CHECK: NEEDED Shared library: [{{.*}}as-needed-no-reloc{{.*}}2.so] .globl _start _start: diff --git a/test/ELF/as-needed.s b/test/ELF/as-needed.s index 4f1a48abac36..37c6103b0ed0 100644 --- a/test/ELF/as-needed.s +++ b/test/ELF/as-needed.s @@ -28,13 +28,13 @@ // RUN: ld.lld %t.o %t.script -o %t2 // RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s -// CHECK: NEEDED SharedLibrary (shared1) -// CHECK: NEEDED SharedLibrary (shared2) -// CHECK: NEEDED SharedLibrary (shared3) +// CHECK: NEEDED Shared library: [shared1] +// CHECK: NEEDED Shared library: [shared2] +// CHECK: NEEDED Shared library: [shared3] -// CHECK2: NEEDED SharedLibrary (shared1) -// CHECK2-NOT: NEEDED SharedLibrary (shared2) -// CHECK2-NOT: NEEDED SharedLibrary (shared3) +// CHECK2: NEEDED Shared library: [shared1] +// CHECK2-NOT: NEEDED Shared library: [shared2] +// CHECK2-NOT: NEEDED Shared library: [shared3] .global _start _start: diff --git a/test/ELF/auxiliary.s b/test/ELF/auxiliary.s index 236d0a421d4f..18fbdf05f9ec 100644 --- a/test/ELF/auxiliary.s +++ b/test/ELF/auxiliary.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: ld.lld %t.o -shared -f aaa --auxiliary bbb -o %t # RUN: llvm-readobj --dynamic-table %t | FileCheck %s diff --git a/test/ELF/compressed-debug-input.s b/test/ELF/compressed-debug-input.s index fbd5b02a07f0..d96ebdcb30b4 100644 --- a/test/ELF/compressed-debug-input.s +++ b/test/ELF/compressed-debug-input.s @@ -1,4 +1,4 @@ -# REQUIRES: zlib +# REQUIRES: zlib, x86 # RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: llvm-readobj -sections %t | FileCheck -check-prefix=ZLIB %s diff --git a/test/ELF/ctors_dtors_priority.s b/test/ELF/ctors_dtors_priority.s index 10d6471f953a..fcddcbb020f3 100644 --- a/test/ELF/ctors_dtors_priority.s +++ b/test/ELF/ctors_dtors_priority.s @@ -14,28 +14,35 @@ _start: nop .section .ctors, "aw", @progbits - .byte 1 + .quad 1 .section .ctors.100, "aw", @progbits - .byte 2 + .quad 2 .section .ctors.005, "aw", @progbits - .byte 3 + .quad 3 .section .ctors, "aw", @progbits - .byte 4 + .quad 4 .section .ctors, "aw", @progbits - .byte 5 + .quad 5 .section .dtors, "aw", @progbits - .byte 0x11 + .quad 0x11 .section .dtors.100, "aw", @progbits - .byte 0x12 + .quad 0x12 .section .dtors.005, "aw", @progbits - .byte 0x13 + .quad 0x13 .section .dtors, "aw", @progbits - .byte 0x14 + .quad 0x14 .section .dtors, "aw", @progbits - .byte 0x15 + .quad 0x15 // CHECK: Contents of section .ctors: -// CHECK-NEXT: a1010405 b10302c1 +// CHECK-NEXT: 202000 a1000000 00000000 01000000 00000000 +// CHECK-NEXT: 202010 04000000 00000000 05000000 00000000 +// CHECK-NEXT: 202020 b1000000 00000000 03000000 00000000 +// CHECK-NEXT: 202030 02000000 00000000 c1000000 00000000 + // CHECK: Contents of section .dtors: -// CHECK-NEXT: a2111415 b21312c2 +// CHECK-NEXT: 202040 a2000000 00000000 11000000 00000000 +// CHECK-NEXT: 202050 14000000 00000000 15000000 00000000 +// CHECK-NEXT: 202060 b2000000 00000000 13000000 00000000 +// CHECK-NEXT: 202070 12000000 00000000 c2000000 00000000 diff --git a/test/ELF/debug-gnu-pubnames.s b/test/ELF/debug-gnu-pubnames.s index 0a8693c97eb8..aebfdfd0fb91 100644 --- a/test/ELF/debug-gnu-pubnames.s +++ b/test/ELF/debug-gnu-pubnames.s @@ -1,10 +1,18 @@ # REQUIRES: x86 -# RUN: ld.lld -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t1.exe -# RUN: llvm-readobj -sections %t1.exe | FileCheck -check-prefix=CHECK1 %s -# CHECK1: Name: .debug_gnu_pubnames -# CHECK1: Name: .debug_gnu_pubtypes - -# RUN: ld.lld -gdb-index -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t2.exe -# RUN: llvm-readobj -sections %t2.exe | FileCheck -check-prefix=CHECK2 %s -# CHECK2-NOT: Name: .debug_gnu_pubnames -# CHECK2-NOT: Name: .debug_gnu_pubtypes +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: ld.lld %t.o -o %t1.exe +# RUN: llvm-readobj -sections %t1.exe | FileCheck %s +# CHECK: .debug_gnu_pubnames +# CHECK: .debug_gnu_pubtypes + +# RUN: ld.lld -gdb-index %t.o -o %t2.exe +# RUN: llvm-readobj -sections %t2.exe | FileCheck %s --check-prefix=GDB +# GDB-NOT: .debug_gnu_pubnames +# GDB-NOT: .debug_gnu_pubtypes + +.section .debug_gnu_pubnames,"",@progbits +.long 0 + +.section .debug_gnu_pubtypes,"",@progbits +.long 0 diff --git a/test/ELF/dynamic-reloc.s b/test/ELF/dynamic-reloc.s index 8fda0b45abea..939093c17b41 100644 --- a/test/ELF/dynamic-reloc.s +++ b/test/ELF/dynamic-reloc.s @@ -43,7 +43,7 @@ // CHECK: DynamicSection [ // CHECK-NEXT: Tag Type Name/Value -// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) +// CHECK-NEXT: 0x0000000000000001 NEEDED Shared library: [{{.*}}2.so] // CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000017 JMPREL // CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes) diff --git a/test/ELF/filter.s b/test/ELF/filter.s new file mode 100644 index 000000000000..fa8e5267b18b --- /dev/null +++ b/test/ELF/filter.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -shared -F foo.so -F boo.so -o %t1 +# RUN: llvm-readobj --dynamic-table %t1 | FileCheck %s + +# Test alias. +# RUN: ld.lld %t.o -shared --filter=foo.so --filter=boo.so -o %t2 +# RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s + +# CHECK: DynamicSection [ +# CHECK-NEXT: Tag Type Name/Value +# CHECK-NEXT: 0x000000007FFFFFFF FILTER Filter library: [foo.so] +# CHECK-NEXT: 0x000000007FFFFFFF FILTER Filter library: [boo.so] + +# RUN: not ld.lld %t.o -F x -o %t 2>&1 | FileCheck -check-prefix=ERR %s +# ERR: -F may not be used without -shared diff --git a/test/ELF/gc-sections-shared.s b/test/ELF/gc-sections-shared.s index a88f2b443479..efb21faee6bd 100644 --- a/test/ELF/gc-sections-shared.s +++ b/test/ELF/gc-sections-shared.s @@ -38,7 +38,7 @@ # CHECK-NEXT: } # CHECK-NEXT: ] -# CHECK: NEEDED SharedLibrary ({{.*}}.so) +# CHECK: NEEDED Shared library: [{{.*}}.so] .section .text.foo, "ax" .globl foo diff --git a/test/ELF/gdb-index-empty.s b/test/ELF/gdb-index-empty.s index 24f20803a008..0158357c9bfd 100644 --- a/test/ELF/gdb-index-empty.s +++ b/test/ELF/gdb-index-empty.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s # RUN: ld.lld --gdb-index --gc-sections -o %t2 %t # RUN: llvm-dwarfdump -debug-dump=gdb_index %t2 | FileCheck %s diff --git a/test/ELF/gdb-index-gc-sections.s b/test/ELF/gdb-index-gc-sections.s index 70a14754656c..58c47ae5e987 100644 --- a/test/ELF/gdb-index-gc-sections.s +++ b/test/ELF/gdb-index-gc-sections.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t %s # RUN: ld.lld --gdb-index --gc-sections -o %t2 %t # RUN: llvm-dwarfdump -debug-dump=gdb_index %t2 | FileCheck %s diff --git a/test/ELF/gdb-index.s b/test/ELF/gdb-index.s index b7d8a708ace5..e04845e022c3 100644 --- a/test/ELF/gdb-index.s +++ b/test/ELF/gdb-index.s @@ -1,32 +1,19 @@ -## gdb-index-a.elf and gdb-index-b.elf are a test.o and test2.o renamed, -## were generated in this way: -## test.cpp: -## int main() { return 0; } -## test2.cpp: -## int main2() { return 0; } -## Compiled with: -## gcc -gsplit-dwarf -c test.cpp test2.cpp -## gcc version 5.3.1 20160413 -## Info about gdb-index: https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html - # REQUIRES: x86 -# RUN: ld.lld --gdb-index -e main %p/Inputs/gdb-index-a.elf %p/Inputs/gdb-index-b.elf -o %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gdb-index.s -o %t2.o +# RUN: ld.lld --gdb-index -e main %t1.o %t2.o -o %t # RUN: llvm-dwarfdump -debug-dump=gdb_index %t | FileCheck %s # RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM # DISASM: Disassembly of section .text: # DISASM: main: -# DISASM-CHECK: 11000: 55 pushq %rbp -# DISASM-CHECK: 11001: 48 89 e5 movq %rsp, %rbp -# DISASM-CHECK: 11004: b8 00 00 00 00 movl $0, %eax -# DISASM-CHECK: 11009: 5d popq %rbp -# DISASM-CHECK: 1100a: c3 retq -# DISASM: _Z5main2v: -# DISASM-CHECK: 1100b: 55 pushq %rbp -# DISASM-CHECK: 1100c: 48 89 e5 movq %rsp, %rbp -# DISASM-CHECK: 1100f: b8 00 00 00 00 movl $0, %eax -# DISASM-CHECK: 11014: 5d popq %rbp -# DISASM-CHECK: 11015: c3 retq +# DISASM-CHECK: 201000: 90 nop +# DISASM-CHECK: 201001: cc int3 +# DISASM-CHECK: 201002: cc int3 +# DISASM-CHECK: 201003: cc int3 +# DISASM: main2: +# DISASM-CHECK: 201004: 90 nop +# DISASM-CHECK: 201005: 90 nop # CHECK: .gnu_index contents: # CHECK-NEXT: Version = 7 @@ -34,8 +21,8 @@ # CHECK-NEXT: 0: Offset = 0x0, Length = 0x34 # CHECK-NEXT: 1: Offset = 0x34, Length = 0x34 # CHECK: Address area offset = 0x38, has 2 entries: -# CHECK-NEXT: Low/High address = [0x201000, 0x20100b) (Size: 0xb), CU id = 0 -# CHECK-NEXT: Low/High address = [0x20100b, 0x201016) (Size: 0xb), CU id = 1 +# CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 +# CHECK-NEXT: Low/High address = [0x201004, 0x201006) (Size: 0x2), CU id = 1 # CHECK: Symbol table offset = 0x60, size = 1024, filled slots: # CHECK-NEXT: 489: Name offset = 0x1d, CU vector offset = 0x0 # CHECK-NEXT: String name: main, CU vector index: 0 @@ -47,3 +34,79 @@ # CHECK-NEXT: 0(0x0): 0x30000000 # CHECK-NEXT: 1(0x8): 0x90000000 0x90000001 # CHECK-NEXT: 2(0x14): 0x30000001 + +## The following section contents are created by this using gcc 7.1.0: +## echo 'int main() { return 0; }' | gcc -gsplit-dwarf -xc++ -S -o- - + +.text +.Ltext0: +.globl main +.type main, @function +main: + nop +.Letext0: + +.section .debug_info,"",@progbits +.long 0x30 +.value 0x4 +.long 0 +.byte 0x8 +.uleb128 0x1 +.quad .Ltext0 +.quad .Letext0-.Ltext0 +.long 0 +.long 0 +.long 0 +.long 0 +.byte 0x63 +.byte 0x88 +.byte 0xb4 +.byte 0x61 +.byte 0xaa +.byte 0xb6 +.byte 0xb0 +.byte 0x67 + +.section .debug_abbrev,"",@progbits +.uleb128 0x1 +.uleb128 0x11 +.byte 0 +.uleb128 0x11 +.uleb128 0x1 +.uleb128 0x12 +.uleb128 0x7 +.uleb128 0x10 +.uleb128 0x17 +.uleb128 0x2130 +.uleb128 0xe +.uleb128 0x1b +.uleb128 0xe +.uleb128 0x2134 +.uleb128 0x19 +.uleb128 0x2133 +.uleb128 0x17 +.uleb128 0x2131 +.uleb128 0x7 +.byte 0 +.byte 0 +.byte 0 + +.section .debug_gnu_pubnames,"",@progbits +.long 0x18 +.value 0x2 +.long 0 +.long 0x33 +.long 0x18 +.byte 0x30 +.string "main" +.long 0 + +.section .debug_gnu_pubtypes,"",@progbits +.long 0x17 +.value 0x2 +.long 0 +.long 0x33 +.long 0x2b +.byte 0x90 +.string "int" +.long 0 diff --git a/test/ELF/i386-reloc-large-addend.s b/test/ELF/i386-reloc-large-addend.s index b644640404e2..5af584475562 100644 --- a/test/ELF/i386-reloc-large-addend.s +++ b/test/ELF/i386-reloc-large-addend.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj // RUN: echo ".global foo; foo = 0x1" > %t1.s diff --git a/test/ELF/i386-reloc-range.s b/test/ELF/i386-reloc-range.s index 47447d0efa32..4fb5325e5434 100644 --- a/test/ELF/i386-reloc-range.s +++ b/test/ELF/i386-reloc-range.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc %s -o %t.o -triple i386-pc-linux-code16 -filetype=obj // RUN: echo ".global foo; foo = 0x10202" > %t1.s diff --git a/test/ELF/invalid/tls-symbol.s b/test/ELF/invalid/tls-symbol.s index 7c65c6c9f2c7..354ca573d5c0 100644 --- a/test/ELF/invalid/tls-symbol.s +++ b/test/ELF/invalid/tls-symbol.s @@ -1,5 +1,5 @@ # REQUIRES: x86 -## The test file contains a STT_TLS symbol but has no TLS section. +## The test file contains an STT_TLS symbol but has no TLS section. # RUN: not ld.lld %S/Inputs/tls-symbol.elf -o %t 2>&1 | FileCheck %s -# CHECK: has a STT_TLS symbol but doesn't have a PT_TLS section +# CHECK: has an STT_TLS symbol but doesn't have an SHF_TLS section diff --git a/test/ELF/linkerscript/exidx-crash.s b/test/ELF/linkerscript/exidx-crash.s new file mode 100644 index 000000000000..c29d0135414d --- /dev/null +++ b/test/ELF/linkerscript/exidx-crash.s @@ -0,0 +1,7 @@ +# REQUIRES: aarch64 + +# We used to crash on this. + +# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux +# RUN: echo "SECTIONS { .ARM.exidx : { *(.foo) } }" > %t.script +# RUN: ld.lld -T %t.script %t.o -o %t diff --git a/test/ELF/linkerscript/got-write-offset.s b/test/ELF/linkerscript/got-write-offset.s new file mode 100644 index 000000000000..323da7b4a46b --- /dev/null +++ b/test/ELF/linkerscript/got-write-offset.s @@ -0,0 +1,23 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux-gnu %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: .data 0x1000 : { *(.data) } \ +# RUN: .got 0x2000 : { \ +# RUN: LONG(0) \ +# RUN: *(.got) \ +# RUN: } \ +# RUN: };" > %t.script +# RUN: ld.lld -shared -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck %s +.text +.global foo +foo: + movl bar@GOT, %eax +.data +.local bar +bar: + .zero 4 +# CHECK: Contents of section .data: +# CHECK-NEXT: 1000 00000000 +# CHECK: Contents of section .got: +# CHECK-NEXT: 2000 00000000 00100000 diff --git a/test/ELF/linkerscript/output-too-large.s b/test/ELF/linkerscript/output-too-large.s index db021eaa99e0..c892a88a947e 100644 --- a/test/ELF/linkerscript/output-too-large.s +++ b/test/ELF/linkerscript/output-too-large.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o # RUN: echo "SECTIONS { .text : { . = 0xffffffff; *(.text*); } }" > %t.script # RUN: not ld.lld --script %t.script %t.o -o %t 2>&1 | FileCheck %s diff --git a/test/ELF/lto/available-externally.ll b/test/ELF/lto/available-externally.ll index 181042b9d1e1..315e710ec87c 100644 --- a/test/ELF/lto/available-externally.ll +++ b/test/ELF/lto/available-externally.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %p/Inputs/available-externally.ll -o %t2.o ; RUN: ld.lld %t1.o %t2.o -m elf_x86_64 -o %t.so -shared -save-temps diff --git a/test/ELF/lto/comdat2.ll b/test/ELF/lto/comdat2.ll index 1509585f1553..283182155ae6 100644 --- a/test/ELF/lto/comdat2.ll +++ b/test/ELF/lto/comdat2.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared diff --git a/test/ELF/lto/common2.ll b/test/ELF/lto/common2.ll index b44bbac4fda3..2345a203b24c 100644 --- a/test/ELF/lto/common2.ll +++ b/test/ELF/lto/common2.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t1.o ; RUN: ld.lld -m elf_x86_64 %t1.o -o %t -shared -save-temps ; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s diff --git a/test/ELF/lto/common3.ll b/test/ELF/lto/common3.ll index 6d40de547fcd..aea33f443f4c 100644 --- a/test/ELF/lto/common3.ll +++ b/test/ELF/lto/common3.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %S/Inputs/common3.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t -shared -save-temps diff --git a/test/ELF/lto/discard-value-names.ll b/test/ELF/lto/discard-value-names.ll index c71dc386113d..f1e95fe75000 100644 --- a/test/ELF/lto/discard-value-names.ll +++ b/test/ELF/lto/discard-value-names.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 -shared -save-temps %t.o -o %t2.o diff --git a/test/ELF/lto/opt-level.ll b/test/ELF/lto/opt-level.ll index 934bf01b6c32..1065ca775751 100644 --- a/test/ELF/lto/opt-level.ll +++ b/test/ELF/lto/opt-level.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as -o %t.o %s ; RUN: ld.lld -o %t0 -m elf_x86_64 -e main --lto-O0 %t.o ; RUN: llvm-nm %t0 | FileCheck --check-prefix=CHECK-O0 %s diff --git a/test/ELF/lto/opt-remarks.ll b/test/ELF/lto/opt-remarks.ll index 88304205caba..e29cc72bb3cc 100644 --- a/test/ELF/lto/opt-remarks.ll +++ b/test/ELF/lto/opt-remarks.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: rm -f %t.yaml diff --git a/test/ELF/lto/relax-relocs.ll b/test/ELF/lto/relax-relocs.ll index 929e124b2d8e..8e8d9d165787 100644 --- a/test/ELF/lto/relax-relocs.ll +++ b/test/ELF/lto/relax-relocs.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 -save-temps -shared %t.o -o %t.so ; RUN: llvm-readobj -r %t.so.lto.o | FileCheck %s diff --git a/test/ELF/lto/thin-archivecollision.ll b/test/ELF/lto/thin-archivecollision.ll index f1dd5ae4d85f..554c2b02fc40 100644 --- a/test/ELF/lto/thin-archivecollision.ll +++ b/test/ELF/lto/thin-archivecollision.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: opt -module-summary %s -o %t.o ; RUN: mkdir -p %t1 %t2 ; RUN: opt -module-summary %p/Inputs/thin1.ll -o %t1/t.coll.o diff --git a/test/ELF/lto/thinlto.ll b/test/ELF/lto/thinlto.ll index 2036c554a76d..99dd19130d28 100644 --- a/test/ELF/lto/thinlto.ll +++ b/test/ELF/lto/thinlto.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; Basic ThinLTO tests. ; RUN: opt -module-summary %s -o %t.o ; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.o diff --git a/test/ELF/lto/type-merge2.ll b/test/ELF/lto/type-merge2.ll index 45777a7e6a48..6ebbf778dd8e 100644 --- a/test/ELF/lto/type-merge2.ll +++ b/test/ELF/lto/type-merge2.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: llvm-as %p/Inputs/type-merge2.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t.o %t2.o -o %t.so -shared -save-temps diff --git a/test/ELF/lto/unnamed-addr-comdat.ll b/test/ELF/lto/unnamed-addr-comdat.ll index ed48f3ba5e04..29a59415851b 100644 --- a/test/ELF/lto/unnamed-addr-comdat.ll +++ b/test/ELF/lto/unnamed-addr-comdat.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -save-temps -shared ; RUN: llvm-dis %t.so.0.2.internalize.bc -o - | FileCheck %s diff --git a/test/ELF/lto/unnamed-addr-drop.ll b/test/ELF/lto/unnamed-addr-drop.ll index 9142537fe57d..e827cbb435e6 100644 --- a/test/ELF/lto/unnamed-addr-drop.ll +++ b/test/ELF/lto/unnamed-addr-drop.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %S/Inputs/unnamed-addr-drop.ll -o %t2.o ; RUN: ld.lld -m elf_x86_64 %t1.o %t2.o -o %t.so -save-temps -shared diff --git a/test/ELF/lto/unnamed-addr.ll b/test/ELF/lto/unnamed-addr.ll index 6a6dd73dad86..56fe148b0995 100644 --- a/test/ELF/lto/unnamed-addr.ll +++ b/test/ELF/lto/unnamed-addr.ll @@ -1,3 +1,4 @@ +; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld -m elf_x86_64 %t.o -o %t.so -save-temps -shared ; RUN: llvm-dis %t.so.0.4.opt.bc -o - | FileCheck %s diff --git a/test/ELF/many-alloc-sections.s b/test/ELF/many-alloc-sections.s index 441e5ff32d08..648ab8250286 100644 --- a/test/ELF/many-alloc-sections.s +++ b/test/ELF/many-alloc-sections.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o // RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script // FIXME: threads are disable because the test is too slow with them (PR32942). diff --git a/test/ELF/many-sections.s b/test/ELF/many-sections.s index ae923889ddc1..7ef0f7ceaac4 100644 --- a/test/ELF/many-sections.s +++ b/test/ELF/many-sections.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t // RUN: llvm-readobj -t %t | FileCheck %s diff --git a/test/ELF/map-gc-sections.s b/test/ELF/map-gc-sections.s new file mode 100644 index 000000000000..717ab819889d --- /dev/null +++ b/test/ELF/map-gc-sections.s @@ -0,0 +1,9 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t -Map=- --gc-sections | FileCheck %s + +.section .tbss,"awT",@nobits +// CHECK-NOT: foo +.globl foo +foo: +.align 8 +.long 0 diff --git a/test/ELF/merge-section-types.s b/test/ELF/merge-section-types.s index ee80fe177fe0..f8462824684f 100644 --- a/test/ELF/merge-section-types.s +++ b/test/ELF/merge-section-types.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: ld.lld -shared %t.o -o %t // RUN: llvm-readobj -s %t | FileCheck %s diff --git a/test/ELF/new-dtags.test b/test/ELF/new-dtags.test index 334d477622a7..1ae328c6b502 100644 --- a/test/ELF/new-dtags.test +++ b/test/ELF/new-dtags.test @@ -1,3 +1,4 @@ +# REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: ld.lld %t.o -rpath=/somepath -shared --disable-new-dtags -o %t // RUN: ld.lld %t.o -rpath=/somepath -shared --enable-new-dtags -o %t2 diff --git a/test/ELF/no-obj.s b/test/ELF/no-obj.s index eea10a45d879..693cdf1e9d3f 100644 --- a/test/ELF/no-obj.s +++ b/test/ELF/no-obj.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: llvm-ar rcs %t.a %t.o // RUN: not ld.lld -o %t2 -u _start %t.a 2>&1 | FileCheck %s diff --git a/test/ELF/no-soname.s b/test/ELF/no-soname.s index d2c15ed8f9cd..e3869ff5a03c 100644 --- a/test/ELF/no-soname.s +++ b/test/ELF/no-soname.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: mkdir -p %T/no-soname // RUN: ld.lld %t.o -shared -o %T/no-soname/libfoo.so @@ -5,26 +6,26 @@ // RUN: ld.lld %t.o %T/no-soname/libfoo.so -o %t // RUN: llvm-readobj --dynamic-table %t | FileCheck %s -// CHECK: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}/no-soname/libfoo.so) +// CHECK: 0x0000000000000001 NEEDED Shared library: [{{.*}}/no-soname/libfoo.so] // CHECK-NOT: NEEDED // RUN: ld.lld %t.o %T/no-soname/../no-soname/libfoo.so -o %t // RUN: llvm-readobj --dynamic-table %t | FileCheck %s --check-prefix=CHECK2 -// CHECK2: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}/no-soname/../no-soname/libfoo.so) +// CHECK2: 0x0000000000000001 NEEDED Shared library: [{{.*}}/no-soname/../no-soname/libfoo.so] // CHECK2-NOT: NEEDED // RUN: ld.lld %t.o -L%T/no-soname/../no-soname -lfoo -o %t // RUN: llvm-readobj --dynamic-table %t | FileCheck %s --check-prefix=CHECK3 -// CHECK3: 0x0000000000000001 NEEDED SharedLibrary (libfoo.so) +// CHECK3: 0x0000000000000001 NEEDED Shared library: [libfoo.so] // CHECK3-NOT: NEEDED // RUN: ld.lld %t.o -shared -soname libbar.so -o %T/no-soname/libbar.so // RUN: ld.lld %t.o %T/no-soname/libbar.so -o %t // RUN: llvm-readobj --dynamic-table %t | FileCheck %s --check-prefix=CHECK4 -// CHECK4: 0x0000000000000001 NEEDED SharedLibrary (libbar.so) +// CHECK4: 0x0000000000000001 NEEDED Shared library: [libbar.so] // CHECK4-NOT: NEEDED .global _start diff --git a/test/ELF/no-symtab.s b/test/ELF/no-symtab.s index 158bd727f251..af9df13e9768 100644 --- a/test/ELF/no-symtab.s +++ b/test/ELF/no-symtab.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: ld.lld %t.o %p/Inputs/no-symtab.o -o %t .global _start diff --git a/test/ELF/no-undefined.s b/test/ELF/no-undefined.s index fa4d5e928763..493a38987091 100644 --- a/test/ELF/no-undefined.s +++ b/test/ELF/no-undefined.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: not ld.lld --no-undefined -shared %t -o %t.so # RUN: ld.lld -shared %t -o %t1.so diff --git a/test/ELF/pie-weak.s b/test/ELF/pie-weak.s index e74bcdfc09c0..99dbd47488fc 100644 --- a/test/ELF/pie-weak.s +++ b/test/ELF/pie-weak.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -relax-relocations=false -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld -pie %t.o -o %t # RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOCS %s diff --git a/test/ELF/progname.s b/test/ELF/progname.s index 6d91823c9481..be8ab9e31c4f 100644 --- a/test/ELF/progname.s +++ b/test/ELF/progname.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: echo .global __progname > %t2.s // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o diff --git a/test/ELF/relative-dynamic-reloc-pie.s b/test/ELF/relative-dynamic-reloc-pie.s index 25b3e0ac2333..f7c8b3c1516c 100644 --- a/test/ELF/relative-dynamic-reloc-pie.s +++ b/test/ELF/relative-dynamic-reloc-pie.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld -pie %t.o -o %t.pie # RUN: llvm-readobj -r -dyn-symbols %t.pie | FileCheck %s diff --git a/test/ELF/relative-dynamic-reloc.s b/test/ELF/relative-dynamic-reloc.s index 39382124e889..0ed7e40f7436 100644 --- a/test/ELF/relative-dynamic-reloc.s +++ b/test/ELF/relative-dynamic-reloc.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o // RUN: ld.lld -shared %t.o -o %t.so // RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s diff --git a/test/ELF/relocatable-compressed-input.s b/test/ELF/relocatable-compressed-input.s index bdfb2073a1e0..3c0199c33f7d 100644 --- a/test/ELF/relocatable-compressed-input.s +++ b/test/ELF/relocatable-compressed-input.s @@ -1,4 +1,4 @@ -# REQUIRES: zlib +# REQUIRES: x86, zlib # RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 # RUN: llvm-readobj -sections %t1 | FileCheck -check-prefix=GNU %s diff --git a/test/ELF/relocatable-reloc.s b/test/ELF/relocatable-reloc.s index c576073a7510..7c699b9bf314 100644 --- a/test/ELF/relocatable-reloc.s +++ b/test/ELF/relocatable-reloc.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj %s -o %t.o -triple=x86_64-pc-linux // RUN: ld.lld %t.o %t.o -r -o %t2.o // RUN: llvm-readobj -r %t2.o | FileCheck %s diff --git a/test/ELF/relocatable-section-symbol.s b/test/ELF/relocatable-section-symbol.s index 9ac3a91d2c24..57a75ab92f11 100644 --- a/test/ELF/relocatable-section-symbol.s +++ b/test/ELF/relocatable-section-symbol.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: ld.lld -r -o %t %t.o %t.o # RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELA %s diff --git a/test/ELF/relocatable-sections.s b/test/ELF/relocatable-sections.s index d6a922fba482..75ede137293c 100644 --- a/test/ELF/relocatable-sections.s +++ b/test/ELF/relocatable-sections.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o # RUN: ld.lld -r %t1.o -o %t # RUN: llvm-objdump -section-headers %t | FileCheck %s diff --git a/test/ELF/relocatable-tls.s b/test/ELF/relocatable-tls.s index 88d38c2ae4b4..ff04dd2dfccb 100644 --- a/test/ELF/relocatable-tls.s +++ b/test/ELF/relocatable-tls.s @@ -1,3 +1,4 @@ +# REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ # RUN: %S/Inputs/relocatable-tls.s -o %t2.o diff --git a/test/ELF/relocation-shared.s b/test/ELF/relocation-shared.s index e1850944c459..4fba7a5683b0 100644 --- a/test/ELF/relocation-shared.s +++ b/test/ELF/relocation-shared.s @@ -1,3 +1,4 @@ +// REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: ld.lld %t.o -shared -o %t.so // RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s diff --git a/test/ELF/shared-be.s b/test/ELF/shared-be.s index c969793d9d21..0b941d373720 100644 --- a/test/ELF/shared-be.s +++ b/test/ELF/shared-be.s @@ -21,7 +21,7 @@ // CHECK: DynamicSection [ // CHECK-NEXT: Tag Type Name/Value // CHECK-NEXT: 0x000000000000001D RUNPATH foo:bar -// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so) +// CHECK-NEXT: 0x0000000000000001 NEEDED Shared library: [{{.*}}2.so] // CHECK-NEXT: 0x0000000000000015 DEBUG 0x0 // CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]] // CHECK-NEXT: 0x0000000000000008 RELASZ [[RELSIZE]] (bytes) diff --git a/test/ELF/shared.s b/test/ELF/shared.s index 350ef5c602d0..d4c79d914ffb 100644 --- a/test/ELF/shared.s +++ b/test/ELF/shared.s @@ -254,7 +254,7 @@ // CHECK: DynamicSection [ // CHECK-NEXT: Tag Type Name/Value // CHECK-NEXT: 0x0000001D RUNPATH foo:bar -// CHECK-NEXT: 0x00000001 NEEDED SharedLibrary ({{.*}}2.so) +// CHECK-NEXT: 0x00000001 NEEDED Shared library: [{{.*}}2.so] // CHECK-NEXT: 0x00000015 DEBUG 0x0 // CHECK-NEXT: 0x00000011 REL [[RELADDR]] // CHECK-NEXT: 0x00000012 RELSZ [[RELSIZE]] (bytes) diff --git a/test/ELF/soname.s b/test/ELF/soname.s index 65e95ce85add..a26bb30f7a17 100644 --- a/test/ELF/soname.s +++ b/test/ELF/soname.s @@ -4,7 +4,7 @@ // RUN: ld.lld %t.o %t.so %t2.so -o %t // RUN: llvm-readobj --dynamic-table %t | FileCheck %s -// CHECK: 0x0000000000000001 NEEDED SharedLibrary (bar) +// CHECK: 0x0000000000000001 NEEDED Shared library: [bar] // CHECK-NOT: NEEDED .global _start diff --git a/test/ELF/soname2.s b/test/ELF/soname2.s index d446766a799d..9fb8da519bfb 100644 --- a/test/ELF/soname2.s +++ b/test/ELF/soname2.s @@ -2,7 +2,7 @@ // RUN: ld.lld %t.o -shared -soname=foo.so -o %t // RUN: llvm-readobj --dynamic-table %t | FileCheck %s -// CHECK: 0x000000000000000E SONAME LibrarySoname (foo.so) +// CHECK: 0x000000000000000E SONAME Library soname: [foo.so] .global _start _start: diff --git a/test/ELF/symver-archive.s b/test/ELF/symver-archive.s deleted file mode 100644 index be50503a3f5d..000000000000 --- a/test/ELF/symver-archive.s +++ /dev/null @@ -1,15 +0,0 @@ -# REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1 -# RUN: rm -f %t.a -# RUN: llvm-ar rcs %t.a %t1 -# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive1.s -o %t2.o -# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive2.s -o %t3.o -# RUN: ld.lld -o %t.out %t2.o %t3.o %t.a - -.text -.globl x -.type x, @function -x: - -.globl xx -xx = x diff --git a/test/ELF/version-script-twice.s b/test/ELF/version-script-twice.s new file mode 100644 index 000000000000..3aeedd5b5ddc --- /dev/null +++ b/test/ELF/version-script-twice.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 + +# RUN: echo "FBSD_1.1 {}; FBSD_1.2 {};" > %t.ver +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld -shared %t.o -o %t.so --version-script=%t.ver +# RUN: llvm-readobj --dyn-symbols --elf-output-style=GNU %t.so | FileCheck %s + + .weak openat +openat: +openat@FBSD_1.1 = openat +openat@@FBSD_1.2 = openat + +# CHECK-DAG: openat@FBSD_1.1 +# CHECK-DAG: openat@@FBSD_1.2 |