diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:45 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:33:45 +0000 |
commit | 4ea16835ba66f2240d050ffcaee44cee6c97cab9 (patch) | |
tree | d2f3d66f3352a3ec22362de0b7a5c1366fc25df8 | |
parent | 15f7a1a3796209b21af2817fdf11ca9932165c70 (diff) |
Vendor import of lld trunk r306325:vendor/lld/lld-trunk-r306325
Notes
Notes:
svn path=/vendor/lld/dist/; revision=320382
svn path=/vendor/lld/lld-trunk-r306325/; revision=320383; tag=vendor/lld/lld-trunk-r306325
106 files changed, 3814 insertions, 549 deletions
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp index 359dbe69559f..56124acaf9a1 100644 --- a/COFF/Chunks.cpp +++ b/COFF/Chunks.cpp @@ -37,8 +37,14 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H) Align = Header->getAlignment(); - // Only COMDAT sections are subject of dead-stripping. - Live = !isCOMDAT(); + // Chunks may be discarded during comdat merging. + Discarded = false; + + // If linker GC is disabled, every chunk starts out alive. If linker GC is + // enabled, treat non-comdat sections as roots. Generally optimized object + // files will be built with -ffunction-sections or /Gy, so most things worth + // stripping will be in a comdat. + Live = !Config->DoGC || !isCOMDAT(); } static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); } @@ -46,6 +52,15 @@ static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); } +static void applySecRel(const SectionChunk *Sec, uint8_t *Off, Defined *Sym) { + // Don't apply section relative relocations to absolute symbols in codeview + // debug info sections. MSVC does not treat such relocations as fatal errors, + // and they can be found in the standard library for linker-provided symbols + // like __guard_fids_table and __safe_se_handler_table. + if (!(isa<DefinedAbsolute>(Sym) && Sec->isCodeView())) + add32(Off, Sym->getSecrel()); +} + void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const { uint64_t S = Sym->getRVA(); @@ -60,7 +75,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym, case IMAGE_REL_AMD64_REL32_4: add32(Off, S - P - 8); break; case IMAGE_REL_AMD64_REL32_5: add32(Off, S - P - 9); break; case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break; - case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break; + case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, Sym); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } @@ -75,7 +90,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym, case IMAGE_REL_I386_DIR32NB: add32(Off, S); break; case IMAGE_REL_I386_REL32: add32(Off, S - P - 4); break; case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break; - case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break; + case IMAGE_REL_I386_SECREL: applySecRel(this, Off, Sym); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } @@ -135,7 +150,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym, case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, S - P - 4); break; case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, S - P - 4); break; case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, S - P - 4); break; - case IMAGE_REL_ARM_SECREL: add32(Off, Sym->getSecrel()); break; + case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, Sym); break; default: fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } @@ -226,8 +241,12 @@ bool SectionChunk::isCOMDAT() const { void SectionChunk::printDiscardedMessage() const { // Removed by dead-stripping. If it's removed by ICF, ICF already // printed out the name, so don't repeat that here. - if (Sym && this == Repl) - message("Discarded " + Sym->getName()); + if (Sym && this == Repl) { + if (Discarded) + message("Discarded comdat symbol " + Sym->getName()); + else if (!Live) + message("Discarded " + Sym->getName()); + } } StringRef SectionChunk::getDebugName() { diff --git a/COFF/Chunks.h b/COFF/Chunks.h index f7412517765c..54fffc5f6d08 100644 --- a/COFF/Chunks.h +++ b/COFF/Chunks.h @@ -64,7 +64,6 @@ public: uint64_t getRVA() const { return RVA; } uint32_t getAlign() const { return Align; } void setRVA(uint64_t V) { RVA = V; } - void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; } // Returns true if this has non-zero data. BSS chunks return // false. If false is returned, the space occupied by this chunk @@ -97,17 +96,19 @@ protected: Chunk(Kind K = OtherKind) : ChunkKind(K) {} const Kind ChunkKind; + // The alignment of this chunk. The writer uses the value. + uint32_t Align = 1; + // The RVA of this chunk in the output. The writer sets a value. uint64_t RVA = 0; +public: // The offset from beginning of the output section. The writer sets a value. uint64_t OutputSectionOff = 0; +protected: // The output section for this chunk. OutputSection *Out = nullptr; - - // The alignment of this chunk. The writer uses the value. - uint32_t Align = 1; }; // A chunk corresponding a section of an input file. @@ -159,13 +160,29 @@ public: StringRef getDebugName() override; void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; } + // Returns true if the chunk was not dropped by GC or COMDAT deduplication. + bool isLive() { return Live && !Discarded; } + // Used by the garbage collector. - bool isLive() { return !Config->DoGC || Live; } void markLive() { + assert(Config->DoGC && "should only mark things live from GC"); assert(!isLive() && "Cannot mark an already live section!"); Live = true; } + // Returns true if this chunk was dropped by COMDAT deduplication. + bool isDiscarded() const { return Discarded; } + + // Used by the SymbolTable when discarding unused comdat sections. This is + // redundant when GC is enabled, as all comdat sections will start out dead. + void markDiscarded() { Discarded = true; } + + // True if this is a codeview debug info chunk. These will not be laid out in + // the image. Instead they will end up in the PDB, if one is requested. + bool isCodeView() const { + return SectionName == ".debug" || 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()), @@ -196,6 +213,9 @@ private: llvm::iterator_range<const coff_relocation *> Relocs; size_t NumRelocs; + // True if this chunk was discarded because it was a duplicate comdat section. + bool Discarded; + // Used by the garbage collector. bool Live; diff --git a/COFF/Config.h b/COFF/Config.h index d859b1fbb7d9..9fcea96d65d3 100644 --- a/COFF/Config.h +++ b/COFF/Config.h @@ -161,9 +161,6 @@ struct Configuration { bool LargeAddressAware = false; bool HighEntropyVA = false; bool AppContainer = false; - - // This is for debugging. - bool DumpPdb = false; }; extern Configuration *Config; diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp index 71a9c679d19f..22efb312ae49 100644 --- a/COFF/Driver.cpp +++ b/COFF/Driver.cpp @@ -905,7 +905,6 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { Config->TerminalServerAware = false; if (Args.hasArg(OPT_nosymtab)) Config->WriteSymtab = false; - Config->DumpPdb = Args.hasArg(OPT_dumppdb); Config->MapFile = getMapFile(Args); @@ -936,9 +935,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { Config->Machine = AMD64; } - // Windows specific -- Input files can be Windows resource files (.res files). - // We invoke cvtres.exe to convert resource files to a regular COFF file - // then link the result file normally. + // Input files can be Windows resource files (.res files). We use + // WindowsResource to convert resource files to a regular COFF file, + // then link the resulting file normally. if (!Resources.empty()) addBuffer(convertResToCOFF(Resources)); @@ -1027,17 +1026,21 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { if (Config->ImageBase == uint64_t(-1)) Config->ImageBase = getDefaultImageBase(); - Symtab.addRelative(mangle("__ImageBase"), 0); + Symtab.addSynthetic(mangle("__ImageBase"), nullptr); if (Config->Machine == I386) { - Config->SEHTable = Symtab.addRelative("___safe_se_handler_table", 0); - Config->SEHCount = Symtab.addAbsolute("___safe_se_handler_count", 0); + Symtab.addAbsolute("___safe_se_handler_table", 0); + Symtab.addAbsolute("___safe_se_handler_count", 0); } // We do not support /guard:cf (control flow protection) yet. // Define CFG symbols anyway so that we can link MSVC 2015 CRT. - Symtab.addAbsolute(mangle("__guard_fids_table"), 0); Symtab.addAbsolute(mangle("__guard_fids_count"), 0); + Symtab.addAbsolute(mangle("__guard_fids_table"), 0); Symtab.addAbsolute(mangle("__guard_flags"), 0x100); + Symtab.addAbsolute(mangle("__guard_iat_count"), 0); + Symtab.addAbsolute(mangle("__guard_iat_table"), 0); + Symtab.addAbsolute(mangle("__guard_longjmp_count"), 0); + Symtab.addAbsolute(mangle("__guard_longjmp_table"), 0); // This code may add new undefined symbols to the link, which may enqueue more // symbol resolution tasks, so we need to continue executing tasks until we diff --git a/COFF/Driver.h b/COFF/Driver.h index 3eb950cca25c..2b5d1e7ae28b 100644 --- a/COFF/Driver.h +++ b/COFF/Driver.h @@ -178,7 +178,7 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects); // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, -#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, #include "Options.inc" #undef OPTION }; diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp index 42619b8fa438..d0152b0917b6 100644 --- a/COFF/DriverUtils.cpp +++ b/COFF/DriverUtils.cpp @@ -20,12 +20,15 @@ #include "Symbols.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/WindowsResource.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" @@ -41,6 +44,9 @@ namespace lld { namespace coff { namespace { +const uint16_t SUBLANG_ENGLISH_US = 0x0409; +const uint16_t RT_MANIFEST = 24; + class Executor { public: explicit Executor(StringRef S) : Prog(Saver.save(S)) {} @@ -257,26 +263,6 @@ void parseManifestUAC(StringRef Arg) { } } -// Quote each line with "". Existing double-quote is converted -// to two double-quotes. -static void quoteAndPrint(raw_ostream &Out, StringRef S) { - while (!S.empty()) { - StringRef Line; - std::tie(Line, S) = S.split("\n"); - if (Line.empty()) - continue; - Out << '\"'; - for (int I = 0, E = Line.size(); I != E; ++I) { - if (Line[I] == '\"') { - Out << "\"\""; - } else { - Out << Line[I]; - } - } - Out << "\"\n"; - } -} - // An RAII temporary file class that automatically removes a temporary file. namespace { class TemporaryFile { @@ -390,38 +376,64 @@ static std::string createManifestXml() { return readFile(File2.Path); } +static std::unique_ptr<MemoryBuffer> +createMemoryBufferForManifestRes(size_t ManifestSize) { + size_t ResSize = alignTo(object::WIN_RES_MAGIC_SIZE + + object::WIN_RES_NULL_ENTRY_SIZE + + sizeof(object::WinResHeaderPrefix) + + sizeof(object::WinResIDs) + + sizeof(object::WinResHeaderSuffix) + + ManifestSize, + object::WIN_RES_DATA_ALIGNMENT); + return MemoryBuffer::getNewMemBuffer(ResSize); +} + +static void writeResFileHeader(char *&Buf) { + memcpy(Buf, COFF::WinResMagic, sizeof(COFF::WinResMagic)); + Buf += sizeof(COFF::WinResMagic); + memset(Buf, 0, object::WIN_RES_NULL_ENTRY_SIZE); + Buf += object::WIN_RES_NULL_ENTRY_SIZE; +} + +static void writeResEntryHeader(char *&Buf, size_t ManifestSize) { + // Write the prefix. + auto *Prefix = reinterpret_cast<object::WinResHeaderPrefix *>(Buf); + Prefix->DataSize = ManifestSize; + Prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) + + sizeof(object::WinResIDs) + + sizeof(object::WinResHeaderSuffix); + Buf += sizeof(object::WinResHeaderPrefix); + + // Write the Type/Name IDs. + auto *IDs = reinterpret_cast<object::WinResIDs *>(Buf); + IDs->setType(RT_MANIFEST); + IDs->setName(Config->ManifestID); + Buf += sizeof(object::WinResIDs); + + // Write the suffix. + auto *Suffix = reinterpret_cast<object::WinResHeaderSuffix *>(Buf); + Suffix->DataVersion = 0; + Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE; + Suffix->Language = SUBLANG_ENGLISH_US; + Suffix->Version = 0; + Suffix->Characteristics = 0; + Buf += sizeof(object::WinResHeaderSuffix); +} + // Create a resource file containing a manifest XML. std::unique_ptr<MemoryBuffer> createManifestRes() { - // Create a temporary file for the resource script file. - TemporaryFile RCFile("manifest", "rc"); + std::string Manifest = createManifestXml(); - // Open the temporary file for writing. - std::error_code EC; - raw_fd_ostream Out(RCFile.Path, EC, sys::fs::F_Text); - if (EC) - fatal(EC, "failed to open " + RCFile.Path); - - // Write resource script to the RC file. - Out << "#define LANG_ENGLISH 9\n" - << "#define SUBLANG_DEFAULT 1\n" - << "#define APP_MANIFEST " << Config->ManifestID << "\n" - << "#define RT_MANIFEST 24\n" - << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n" - << "APP_MANIFEST RT_MANIFEST {\n"; - quoteAndPrint(Out, createManifestXml()); - Out << "}\n"; - Out.close(); - - // Create output resource file. - TemporaryFile ResFile("output-resource", "res"); - - Executor E("rc.exe"); - E.add("/fo"); - E.add(ResFile.Path); - E.add("/nologo"); - E.add(RCFile.Path); - E.run(); - return ResFile.getMemoryBuffer(); + std::unique_ptr<MemoryBuffer> Res = + createMemoryBufferForManifestRes(Manifest.size()); + + char *Buf = const_cast<char *>(Res->getBufferStart()); + writeResFileHeader(Buf); + writeResEntryHeader(Buf, Manifest.size()); + + // Copy the manifest data into the .res file. + std::copy(Manifest.begin(), Manifest.end(), Buf); + return Res; } void createSideBySideManifest() { @@ -592,40 +604,22 @@ void checkFailIfMismatch(StringRef Arg) { // using cvtres.exe. std::unique_ptr<MemoryBuffer> convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) { - // Create an output file path. - TemporaryFile File("resource-file", "obj"); + object::WindowsResourceParser Parser; - // Execute cvtres.exe. - Executor E("cvtres.exe"); - E.add("/machine:" + machineToStr(Config->Machine)); - E.add("/readonly"); - E.add("/nologo"); - E.add("/out:" + Twine(File.Path)); - - // We must create new files because the memory buffers we have may have no - // underlying file still existing on the disk. - // It happens if it was created from a TemporaryFile, which usually delete - // the file just after creating the MemoryBuffer. - std::vector<TemporaryFile> ResFiles; - ResFiles.reserve(MBs.size()); for (MemoryBufferRef MB : MBs) { - // We store the temporary file in a vector to avoid deletion - // before running cvtres - ResFiles.emplace_back("resource-file", "res"); - TemporaryFile& ResFile = ResFiles.back(); - // Write the content of the resource in a temporary file - std::error_code EC; - raw_fd_ostream OS(ResFile.Path, EC, sys::fs::F_None); - if (EC) - fatal(EC, "failed to open " + ResFile.Path); - OS << MB.getBuffer(); - OS.close(); - - E.add(ResFile.Path); + std::unique_ptr<object::Binary> Bin = check(object::createBinary(MB)); + object::WindowsResource *RF = dyn_cast<object::WindowsResource>(Bin.get()); + if (!RF) + fatal("cannot compile non-resource file as resource"); + if (auto EC = Parser.parse(RF)) + fatal(EC, "failed to parse .res file"); } - E.run(); - return File.getMemoryBuffer(); + Expected<std::unique_ptr<MemoryBuffer>> E = + llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser); + if (!E) + fatal(errorToErrorCode(E.takeError()), "failed to write .res to COFF"); + return std::move(E.get()); } // Run MSVC link.exe for given in-memory object files. @@ -657,11 +651,9 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) { // Create table mapping all options defined in Options.td static const llvm::opt::OptTable::Info infoTable[] = { -#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ - { \ - X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ - OPT_##GROUP, OPT_##ALIAS, X6 \ - }, +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ + {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \ + X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, #include "Options.inc" #undef OPTION }; diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp index 58e8dd329f1f..c26483e3e368 100644 --- a/COFF/InputFiles.cpp +++ b/COFF/InputFiles.cpp @@ -132,17 +132,17 @@ void ObjectFile::initializeChunks() { if (!Config->Debug && Name.startswith(".debug")) continue; - // CodeView sections are stored to a different vector because they are - // not linked in the regular manner. - if (Name == ".debug" || Name.startswith(".debug$")) { - DebugChunks.push_back(make<SectionChunk>(this, Sec)); - continue; - } - if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) continue; auto *C = make<SectionChunk>(this, Sec); - Chunks.push_back(C); + + // CodeView sections are stored to a different vector because they are not + // linked in the regular manner. + if (C->isCodeView()) + DebugChunks.push_back(C); + else + Chunks.push_back(C); + SparseChunks[I] = C; } } @@ -249,8 +249,12 @@ SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP, auto *Aux = reinterpret_cast<const coff_aux_section_definition *>(AuxP); if (Aux->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) if (auto *ParentSC = cast_or_null<SectionChunk>( - SparseChunks[Aux->getNumber(Sym.isBigObj())])) + SparseChunks[Aux->getNumber(Sym.isBigObj())])) { ParentSC->addAssociative(SC); + // If we already discarded the parent, discard the child. + if (ParentSC->isDiscarded()) + SC->markDiscarded(); + } SC->Checksum = Aux->CheckSum; } diff --git a/COFF/Options.td b/COFF/Options.td index 14a1aa04afd6..61523c4f2256 100644 --- a/COFF/Options.td +++ b/COFF/Options.td @@ -102,7 +102,6 @@ def nosymtab : F<"nosymtab">; def msvclto : F<"msvclto">; // Flags for debugging -def dumppdb : Joined<["/", "-"], "dumppdb">; def lldmap : F<"lldmap">; def lldmap_file : Joined<["/", "-"], "lldmap:">; diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp index 116766740e58..c9842cfd1b9a 100644 --- a/COFF/PDB.cpp +++ b/COFF/PDB.cpp @@ -15,10 +15,11 @@ #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/SymbolDumper.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.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" @@ -46,8 +47,6 @@ using namespace lld; using namespace lld::coff; using namespace llvm; using namespace llvm::codeview; -using namespace llvm::support; -using namespace llvm::support::endian; using llvm::object::coff_section; @@ -68,22 +67,24 @@ static SectionChunk *findByName(std::vector<SectionChunk *> &Sections, return nullptr; } -static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) { - SectionChunk *Sec = findByName(File->getDebugChunks(), SecName); - if (!Sec) - return {}; - +static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> Data, + StringRef SecName) { // First 4 bytes are section magic. - ArrayRef<uint8_t> Data = Sec->getContents(); if (Data.size() < 4) fatal(SecName + " too short"); - if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) + if (support::endian::read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) fatal(SecName + " has an invalid magic"); return Data.slice(4); } +static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) { + if (SectionChunk *Sec = findByName(File->getDebugChunks(), SecName)) + return consumeDebugMagic(Sec->getContents(), SecName); + return {}; +} + static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, - codeview::TypeTableBuilder &TypeTable) { + TypeTableBuilder &TypeTable) { // Start the TPI or IPI stream header. TpiBuilder.setVersionHeader(pdb::PdbTpiV80); @@ -94,17 +95,148 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, }); } +static void mergeDebugT(ObjectFile *File, + TypeTableBuilder &IDTable, + TypeTableBuilder &TypeTable, + SmallVectorImpl<TypeIndex> &TypeIndexMap, + pdb::PDBTypeServerHandler &Handler) { + ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); + if (Data.empty()) + return; + + 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"); + if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, + TypeIndexMap, &Handler, Types)) + fatal(Err, "codeview::mergeTypeStreams failed"); +} + +static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { + if (TI.isSimple()) + return true; + if (TI.toArrayIndex() >= TypeIndexMap.size()) + return false; + TI = TypeIndexMap[TI.toArrayIndex()]; + return true; +} + +static bool remapTypesInSymbolRecord(ObjectFile *File, + MutableArrayRef<uint8_t> Contents, + ArrayRef<TypeIndex> TypeIndexMap, + ArrayRef<TiReference> TypeRefs) { + for (const TiReference &Ref : TypeRefs) { + unsigned ByteSize = Ref.Count * sizeof(TypeIndex); + if (Contents.size() < Ref.Offset + ByteSize) { + log("ignoring short symbol record"); + return false; + } + MutableArrayRef<TypeIndex> TIs( + reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count); + for (TypeIndex &TI : TIs) + if (!remapTypeIndex(TI, TypeIndexMap)) { + log("ignoring symbol record in " + File->getName() + + " with bad type index 0x" + utohexstr(TI.getIndex())); + return false; + } + } + return true; +} + +/// MSVC translates S_PROC_ID_END to S_END. +uint16_t canonicalizeSymbolKind(SymbolKind Kind) { + if (Kind == SymbolKind::S_PROC_ID_END) + return SymbolKind::S_END; + return Kind; +} + +/// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. +/// The object file may not be aligned. +static MutableArrayRef<uint8_t> copySymbolForPdb(const CVSymbol &Sym, + BumpPtrAllocator &Alloc) { + size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); + assert(Size >= 4 && "record too short"); + assert(Size <= MaxRecordLength && "record too long"); + void *Mem = Alloc.Allocate(Size, 4); + + // Copy the symbol record and zero out any padding bytes. + MutableArrayRef<uint8_t> NewData(reinterpret_cast<uint8_t *>(Mem), Size); + memcpy(NewData.data(), Sym.data().data(), Sym.length()); + memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); + + // Update the record prefix length. It should point to the beginning of the + // next record. MSVC does some canonicalization of the record kind, so we do + // that as well. + auto *Prefix = reinterpret_cast<RecordPrefix *>(Mem); + Prefix->RecordKind = canonicalizeSymbolKind(Sym.kind()); + Prefix->RecordLen = Size - 2; + return NewData; +} + +static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File, + ArrayRef<TypeIndex> TypeIndexMap, + BinaryStreamRef SymData) { + // FIXME: Improve error recovery by warning and skipping records when + // possible. + CVSymbolArray Syms; + BinaryStreamReader Reader(SymData); + ExitOnErr(Reader.readArray(Syms, Reader.getLength())); + for (const CVSymbol &Sym : Syms) { + // Discover type index references in the record. Skip it if we don't know + // where they are. + SmallVector<TiReference, 32> TypeRefs; + if (!discoverTypeIndices(Sym, TypeRefs)) { + log("ignoring unknown symbol record with kind 0x" + utohexstr(Sym.kind())); + continue; + } + + // Copy the symbol record so we can mutate it. + MutableArrayRef<uint8_t> NewData = copySymbolForPdb(Sym, Alloc); + + // Re-map all the type index references. + MutableArrayRef<uint8_t> Contents = + NewData.drop_front(sizeof(RecordPrefix)); + if (!remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs)) + continue; + + // FIXME: Fill in "Parent" and "End" fields by maintaining a stack of + // scopes. + + // Add the symbol to the module. + File->ModuleDBI->addSymbol(CVSymbol(Sym.kind(), NewData)); + } +} + +// Allocate memory for a .debug$S section and relocate it. +static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc, + SectionChunk *DebugChunk) { + uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk->getSize()); + assert(DebugChunk->OutputSectionOff == 0 && + "debug sections should not be in output sections"); + DebugChunk->writeTo(Buffer); + return consumeDebugMagic(makeArrayRef(Buffer, DebugChunk->getSize()), + ".debug$S"); +} + // Add all object files to the PDB. Merge .debug$T sections into IpiData and // TpiData. -static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder, - codeview::TypeTableBuilder &TypeTable, - codeview::TypeTableBuilder &IDTable) { +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 @@ -118,25 +250,74 @@ static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder, File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); File->ModuleDBI->setObjFileName(Path); - // FIXME: Walk the .debug$S sections and add them. Do things like recording - // source files. - - ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); - if (Data.empty()) - continue; - - BinaryByteStream Stream(Data, support::little); - codeview::CVTypeArray Types; - BinaryStreamReader Reader(Stream); - SmallVector<TypeIndex, 128> SourceToDest; - Handler.addSearchPath(llvm::sys::path::parent_path(File->getName())); - if (auto EC = Reader.readArray(Types, Reader.getLength())) - fatal(EC, "Reader::readArray failed"); - if (auto Err = codeview::mergeTypeAndIdRecords( - IDTable, TypeTable, SourceToDest, &Handler, Types)) - fatal(Err, "codeview::mergeTypeStreams failed"); + // 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; + + 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; + } + } + + 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)); + } + } } + Builder.getStringTableBuilder().setStrings(*PDBStrTab); + // Construct TPI stream contents. addTypeInfo(Builder.getTpiBuilder(), TypeTable); @@ -144,56 +325,10 @@ static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder, addTypeInfo(Builder.getIpiBuilder(), IDTable); } -static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) { - ListScope LS(W, "DebugT"); - ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); - if (Data.empty()) - return; - - LazyRandomTypeCollection Types(Data, 100); - TypeDumpVisitor TDV(Types, &W, false); - // Use a default implementation that does not follow type servers and instead - // just dumps the contents of the TypeServer2 record. - if (auto EC = codeview::visitTypeStream(Types, TDV)) - fatal(EC, "CVTypeDumper::dump failed"); -} - -static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) { - ListScope LS(W, "DebugS"); - ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S"); - if (Data.empty()) - return; - - BinaryByteStream Stream(Data, llvm::support::little); - CVSymbolArray Symbols; - BinaryStreamReader Reader(Stream); - if (auto EC = Reader.readArray(Symbols, Reader.getLength())) - fatal(EC, "StreamReader.readArray<CVSymbolArray> failed"); - - TypeDatabase TDB(0); - CVSymbolDumper SymbolDumper(W, TDB, CodeViewContainer::ObjectFile, nullptr, - false); - if (auto EC = SymbolDumper.dump(Symbols)) - fatal(EC, "CVSymbolDumper::dump failed"); -} - -// Dump CodeView debug info. This is for debugging. -static void dumpCodeView(SymbolTable *Symtab) { - ScopedPrinter W(outs()); - - for (ObjectFile *File : Symtab->ObjectFiles) { - dumpDebugT(W, File); - dumpDebugS(W, File); - } -} - // Creates a PDB file. void coff::createPDB(StringRef Path, SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable, const llvm::codeview::DebugInfo *DI) { - if (Config->DumpPdb) - dumpCodeView(Symtab); - BumpPtrAllocator Alloc; pdb::PDBFileBuilder Builder(Alloc); ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize @@ -219,9 +354,9 @@ void coff::createPDB(StringRef Path, SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); DbiBuilder.setVersionHeader(pdb::PdbDbiV110); - codeview::TypeTableBuilder TypeTable(BAlloc); - codeview::TypeTableBuilder IDTable(BAlloc); - addObjectsToPDB(Symtab, Builder, TypeTable, IDTable); + TypeTableBuilder TypeTable(BAlloc); + TypeTableBuilder IDTable(BAlloc); + addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable); // Add Section Contributions. addSectionContribs(Symtab, DbiBuilder); diff --git a/COFF/Strings.cpp b/COFF/Strings.cpp index d0558413f673..84f9b9a55a32 100644 --- a/COFF/Strings.cpp +++ b/COFF/Strings.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "Strings.h" +#include <mutex> #if defined(_MSC_VER) #include <Windows.h> @@ -21,6 +22,10 @@ using namespace llvm; Optional<std::string> coff::demangle(StringRef S) { #if defined(_MSC_VER) + // UnDecorateSymbolName is not thread-safe, so we need a mutex. + static std::mutex Mu; + std::lock_guard<std::mutex> Lock(Mu); + char Buf[4096]; if (S.startswith("?")) if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0)) diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp index 310eab274526..c06e42bb114b 100644 --- a/COFF/SymbolTable.cpp +++ b/COFF/SymbolTable.cpp @@ -219,13 +219,13 @@ Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) { return S; } -Symbol *SymbolTable::addRelative(StringRef N, uint64_t VA) { +Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N); S->IsUsedInRegularObj = true; if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) - replaceBody<DefinedRelative>(S, N, VA); + replaceBody<DefinedSynthetic>(S, N, C); else if (!isa<DefinedCOFF>(S->body())) reportDuplicate(S, nullptr); return S; @@ -244,6 +244,12 @@ Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, bool IsCOMDAT, reportDuplicate(S, F); } else if (SP == SP_NEW) { replaceBody<DefinedRegular>(S, F, N, IsCOMDAT, /*IsExternal*/ true, Sym, C); + } else if (SP == SP_EXISTING && IsCOMDAT && C) { + C->markDiscarded(); + // Discard associative chunks that we've parsed so far. No need to recurse + // because an associative section cannot have children. + for (SectionChunk *Child : C->children()) + Child->markDiscarded(); } return S; } diff --git a/COFF/SymbolTable.h b/COFF/SymbolTable.h index 0aa8a4593b5c..ea74678c28d8 100644 --- a/COFF/SymbolTable.h +++ b/COFF/SymbolTable.h @@ -85,7 +85,7 @@ public: // Creates an Undefined symbol for a given name. SymbolBody *addUndefined(StringRef Name); - Symbol *addRelative(StringRef N, uint64_t VA); + Symbol *addSynthetic(StringRef N, Chunk *C); Symbol *addAbsolute(StringRef N, uint64_t VA); Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias); diff --git a/COFF/Symbols.cpp b/COFF/Symbols.cpp index 5c185a511dd7..1cf2934a355b 100644 --- a/COFF/Symbols.cpp +++ b/COFF/Symbols.cpp @@ -61,6 +61,8 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() { return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym)); } +uint16_t DefinedAbsolute::OutputSectionIndex = 0; + static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) { if (Machine == AMD64) return make<ImportThunkChunkX64>(S); diff --git a/COFF/Symbols.h b/COFF/Symbols.h index 801fc87f91d9..8c1390c45876 100644 --- a/COFF/Symbols.h +++ b/COFF/Symbols.h @@ -50,13 +50,13 @@ public: DefinedImportThunkKind, DefinedImportDataKind, DefinedAbsoluteKind, - DefinedRelativeKind, + DefinedSyntheticKind, UndefinedKind, LazyKind, LastDefinedCOFFKind = DefinedCommonKind, - LastDefinedKind = DefinedRelativeKind, + LastDefinedKind = DefinedSyntheticKind, }; Kind kind() const { return static_cast<Kind>(SymbolKind); } @@ -112,11 +112,11 @@ public: // Returns the RVA relative to the beginning of the output section. // Used to implement SECREL relocation type. - uint64_t getSecrel(); + uint32_t getSecrel(); // Returns the output section index. // Used to implement SECTION relocation type. - uint64_t getSectionIndex(); + uint16_t getSectionIndex(); // Returns true if this symbol points to an executable (e.g. .text) section. // Used to implement ARM relocations. @@ -167,6 +167,7 @@ public: bool isCOMDAT() { return IsCOMDAT; } SectionChunk *getChunk() { return *Data; } uint32_t getValue() { return Sym->Value; } + uint32_t getSecrel(); private: SectionChunk **Data; @@ -186,6 +187,8 @@ public: } uint64_t getRVA() { return Data->getRVA(); } + uint32_t getSecrel() { return Data->OutputSectionOff; } + uint16_t getSectionIndex(); private: friend SymbolTable; @@ -212,28 +215,34 @@ public: uint64_t getRVA() { return VA - Config->ImageBase; } void setVA(uint64_t V) { VA = V; } + // The sentinel absolute symbol section index. Section index relocations + // against absolute symbols resolve to this 16 bit number, and it is the + // largest valid section index plus one. This is written by the Writer. + static uint16_t OutputSectionIndex; + private: uint64_t VA; }; -// This is a kind of absolute symbol but relative to the image base. -// Unlike absolute symbols, relocations referring this kind of symbols -// are subject of the base relocation. This type is used rarely -- -// mainly for __ImageBase. -class DefinedRelative : public Defined { +// This symbol is used for linker-synthesized symbols like __ImageBase and +// __safe_se_handler_table. +class DefinedSynthetic : public Defined { public: - explicit DefinedRelative(StringRef Name, uint64_t V = 0) - : Defined(DefinedRelativeKind, Name), RVA(V) {} + explicit DefinedSynthetic(StringRef Name, Chunk *C) + : Defined(DefinedSyntheticKind, Name), C(C) {} static bool classof(const SymbolBody *S) { - return S->kind() == DefinedRelativeKind; + return S->kind() == DefinedSyntheticKind; } - uint64_t getRVA() { return RVA; } - void setRVA(uint64_t V) { RVA = V; } + // A null chunk indicates that this is __ImageBase. Otherwise, this is some + // other synthesized chunk, like SEHTableChunk. + uint32_t getRVA() const { return C ? C->getRVA() : 0; } + uint32_t getSecrel() const { return C ? C->OutputSectionOff : 0; } + Chunk *getChunk() const { return C; } private: - uint64_t RVA; + Chunk *C; }; // This class represents a symbol defined in an archive file. It is @@ -350,8 +359,8 @@ inline uint64_t Defined::getRVA() { switch (kind()) { case DefinedAbsoluteKind: return cast<DefinedAbsolute>(this)->getRVA(); - case DefinedRelativeKind: - return cast<DefinedRelative>(this)->getRVA(); + case DefinedSyntheticKind: + return cast<DefinedSynthetic>(this)->getRVA(); case DefinedImportDataKind: return cast<DefinedImportData>(this)->getRVA(); case DefinedImportThunkKind: @@ -386,7 +395,7 @@ struct Symbol { // AlignedCharArrayUnion gives us a struct with a char array field that is // large and aligned enough to store any derived class of SymbolBody. llvm::AlignedCharArrayUnion< - DefinedRegular, DefinedCommon, DefinedAbsolute, DefinedRelative, Lazy, + DefinedRegular, DefinedCommon, DefinedAbsolute, DefinedSynthetic, Lazy, Undefined, DefinedImportData, DefinedImportThunk, DefinedLocalImport> Body; diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp index fb1f3cae5bb2..d32577b361fa 100644 --- a/COFF/Writer.cpp +++ b/COFF/Writer.cpp @@ -181,7 +181,7 @@ void OutputSection::addChunk(Chunk *C) { uint64_t Off = Header.VirtualSize; Off = alignTo(Off, C->getAlign()); C->setRVA(Off); - C->setOutputSectionOff(Off); + C->OutputSectionOff = Off; Off += C->getSize(); Header.VirtualSize = Off; if (C->hasData()) @@ -210,16 +210,46 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { } } -uint64_t Defined::getSecrel() { - if (auto *D = dyn_cast<DefinedRegular>(this)) - return getRVA() - D->getChunk()->getOutputSection()->getRVA(); - fatal("SECREL relocation points to a non-regular symbol"); +uint32_t Defined::getSecrel() { + assert(this); + switch (kind()) { + case DefinedRegularKind: + return cast<DefinedRegular>(this)->getSecrel(); + case DefinedCommonKind: + return cast<DefinedCommon>(this)->getSecrel(); + case DefinedSyntheticKind: + return cast<DefinedSynthetic>(this)->getSecrel(); + default: + break; + } + fatal("SECREL relocation points to a non-regular symbol: " + toString(*this)); +} + +uint32_t DefinedRegular::getSecrel() { + assert(getChunk()->isLive() && "relocation against discarded section"); + uint64_t Diff = getRVA() - getChunk()->getOutputSection()->getRVA(); + assert(Diff < UINT32_MAX && "section offset too large"); + return (uint32_t)Diff; } -uint64_t Defined::getSectionIndex() { +uint16_t Defined::getSectionIndex() { if (auto *D = dyn_cast<DefinedRegular>(this)) return D->getChunk()->getOutputSection()->SectionIndex; - fatal("SECTION relocation points to a non-regular symbol"); + if (isa<DefinedAbsolute>(this)) + return DefinedAbsolute::OutputSectionIndex; + if (auto *D = dyn_cast<DefinedCommon>(this)) + return D->getSectionIndex(); + if (auto *D = dyn_cast<DefinedSynthetic>(this)) { + if (!D->getChunk()) + return 0; + return D->getChunk()->getOutputSection()->SectionIndex; + } + fatal("SECTION relocation points to a non-regular symbol: " + + toString(*this)); +} + +uint16_t DefinedCommon::getSectionIndex() { + return Data->getOutputSection()->SectionIndex; } bool Defined::isExecutable() { @@ -345,12 +375,19 @@ void Writer::createMiscChunks() { for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) { if (!File->SEHCompat) return; - for (SymbolBody *B : File->SEHandlers) - Handlers.insert(cast<Defined>(B)); + for (SymbolBody *B : File->SEHandlers) { + // Make sure the handler is still live. Assume all handlers are regular + // symbols. + auto *D = dyn_cast<DefinedRegular>(B); + if (D && D->getChunk()->isLive()) + Handlers.insert(D); + } } - SEHTable = make<SEHTableChunk>(Handlers); - RData->addChunk(SEHTable); + if (!Handlers.empty()) { + SEHTable = make<SEHTableChunk>(Handlers); + RData->addChunk(SEHTable); + } } // Create .idata section for the DLL-imported symbol table. @@ -442,12 +479,15 @@ size_t Writer::addEntryToStringTable(StringRef Str) { Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { // Relative symbols are unrepresentable in a COFF symbol table. - if (isa<DefinedRelative>(Def)) + if (isa<DefinedSynthetic>(Def)) return None; - if (auto *D = dyn_cast<DefinedRegular>(Def)) - if (!D->getChunk()->isLive()) + if (auto *D = dyn_cast<DefinedRegular>(Def)) { + // Don't write dead symbols or symbols in codeview sections to the symbol + // table. + if (!D->getChunk()->isLive() || D->getChunk()->isCodeView()) return None; + } if (auto *Sym = dyn_cast<DefinedImportData>(Def)) if (!Sym->File->Live) @@ -599,6 +639,15 @@ template <typename PEHeaderTy> void Writer::writeHeader() { auto *PE = reinterpret_cast<PEHeaderTy *>(Buf); Buf += sizeof(*PE); PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32; + + // If {Major,Minor}LinkerVersion is left at 0.0, then for some + // reason signing the resulting PE file with Authenticode produces a + // signature that fails to validate on Windows 7 (but is OK on 10). + // Set it to 14.0, which is what VS2015 outputs, and which avoids + // that problem. + PE->MajorLinkerVersion = 14; + PE->MinorLinkerVersion = 0; + PE->ImageBase = Config->ImageBase; PE->SectionAlignment = PageSize; PE->FileAlignment = SectorSize; @@ -743,10 +792,13 @@ void Writer::openFile(StringRef Path) { void Writer::fixSafeSEHSymbols() { if (!SEHTable) return; - if (auto *T = dyn_cast<DefinedRelative>(Config->SEHTable->body())) - T->setRVA(SEHTable->getRVA()); - if (auto *C = dyn_cast<DefinedAbsolute>(Config->SEHCount->body())) - C->setVA(SEHTable->getSize() / 4); + // Replace the absolute table symbol with a synthetic symbol pointing to the + // SEHTable chunk so that we can emit base relocations for it and resolve + // section relative relocations. + Symbol *T = Symtab->find("___safe_se_handler_table"); + Symbol *C = Symtab->find("___safe_se_handler_count"); + replaceBody<DefinedSynthetic>(T, T->body()->getName(), SEHTable); + cast<DefinedAbsolute>(C->body())->setVA(SEHTable->getSize() / 4); } // Handles /section options to allow users to overwrite @@ -762,6 +814,10 @@ void Writer::setSectionPermissions() { // Write section contents to a mmap'ed file. void Writer::writeSections() { + // Record the section index that should be used when resolving a section + // relocation against an absolute symbol. + DefinedAbsolute::OutputSectionIndex = OutputSections.size() + 1; + uint8_t *Buf = Buffer->getBufferStart(); for (OutputSection *Sec : OutputSections) { uint8_t *SecBuf = Buf + Sec->getFileOff(); diff --git a/ELF/Arch/AArch64.cpp b/ELF/Arch/AArch64.cpp index 113d0960d5f5..b26cf0815109 100644 --- a/ELF/Arch/AArch64.cpp +++ b/ELF/Arch/AArch64.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "Error.h" -#include "Memory.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -371,4 +370,7 @@ void AArch64::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { llvm_unreachable("invalid relocation for TLS IE to LE relaxation"); } -TargetInfo *elf::createAArch64TargetInfo() { return make<AArch64>(); } +TargetInfo *elf::getAArch64TargetInfo() { + static AArch64 Target; + return &Target; +} diff --git a/ELF/Arch/AMDGPU.cpp b/ELF/Arch/AMDGPU.cpp index 68e516f9e6cf..de566c617ac0 100644 --- a/ELF/Arch/AMDGPU.cpp +++ b/ELF/Arch/AMDGPU.cpp @@ -9,7 +9,6 @@ #include "Error.h" #include "InputFiles.h" -#include "Memory.h" #include "Symbols.h" #include "Target.h" #include "llvm/Object/ELF.h" @@ -79,4 +78,7 @@ RelExpr AMDGPU::getRelExpr(uint32_t Type, const SymbolBody &S, } } -TargetInfo *elf::createAMDGPUTargetInfo() { return make<AMDGPU>(); } +TargetInfo *elf::getAMDGPUTargetInfo() { + static AMDGPU Target; + return &Target; +} diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp index b245cbd7005a..e4b06ade4487 100644 --- a/ELF/Arch/ARM.cpp +++ b/ELF/Arch/ARM.cpp @@ -9,7 +9,6 @@ #include "Error.h" #include "InputFiles.h" -#include "Memory.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -58,6 +57,7 @@ ARM::ARM() { GotPltEntrySize = 4; PltEntrySize = 16; PltHeaderSize = 20; + TrapInstr = 0xd4d4d4d4; // ARM uses Variant 1 TLS TcbSize = 8; NeedsThunks = true; @@ -429,4 +429,7 @@ int64_t ARM::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { } } -TargetInfo *elf::createARMTargetInfo() { return make<ARM>(); } +TargetInfo *elf::getARMTargetInfo() { + static ARM Target; + return &Target; +} diff --git a/ELF/Arch/AVR.cpp b/ELF/Arch/AVR.cpp index 86343a6faa16..3853248f8fbd 100644 --- a/ELF/Arch/AVR.cpp +++ b/ELF/Arch/AVR.cpp @@ -28,7 +28,6 @@ #include "Error.h" #include "InputFiles.h" -#include "Memory.h" #include "Symbols.h" #include "Target.h" #include "llvm/Object/ELF.h" @@ -75,4 +74,7 @@ void AVR::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { } } -TargetInfo *elf::createAVRTargetInfo() { return make<AVR>(); } +TargetInfo *elf::getAVRTargetInfo() { + static AVR Target; + return &Target; +} diff --git a/ELF/Arch/Mips.cpp b/ELF/Arch/Mips.cpp index 79642df8a885..b8d796f5897a 100644 --- a/ELF/Arch/Mips.cpp +++ b/ELF/Arch/Mips.cpp @@ -9,7 +9,6 @@ #include "Error.h" #include "InputFiles.h" -#include "Memory.h" #include "OutputSections.h" #include "Symbols.h" #include "SyntheticSections.h" @@ -55,6 +54,7 @@ template <class ELFT> MIPS<ELFT>::MIPS() { CopyRel = R_MIPS_COPY; PltRel = R_MIPS_JUMP_SLOT; NeedsThunks = true; + TrapInstr = 0xefefefef; if (ELFT::Is64Bits) { RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; @@ -412,11 +412,12 @@ bool MIPS<ELFT>::usesOnlyLowPageBits(uint32_t Type) const { return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST; } -template <class ELFT> TargetInfo *elf::createMipsTargetInfo() { - return make<MIPS<ELFT>>(); +template <class ELFT> TargetInfo *elf::getMipsTargetInfo() { + static MIPS<ELFT> Target; + return &Target; } -template TargetInfo *elf::createMipsTargetInfo<ELF32LE>(); -template TargetInfo *elf::createMipsTargetInfo<ELF32BE>(); -template TargetInfo *elf::createMipsTargetInfo<ELF64LE>(); -template TargetInfo *elf::createMipsTargetInfo<ELF64BE>(); +template TargetInfo *elf::getMipsTargetInfo<ELF32LE>(); +template TargetInfo *elf::getMipsTargetInfo<ELF32BE>(); +template TargetInfo *elf::getMipsTargetInfo<ELF64LE>(); +template TargetInfo *elf::getMipsTargetInfo<ELF64BE>(); diff --git a/ELF/Mips.cpp b/ELF/Arch/MipsArchTree.cpp index af92fb9d24fd..ed183e9a3061 100644 --- a/ELF/Mips.cpp +++ b/ELF/Arch/MipsArchTree.cpp @@ -1,4 +1,4 @@ -//===- Mips.cpp ----------------------------------------------------------===// +//===- MipsArchTree.cpp --------------------------------------------------===// // // The LLVM Linker // diff --git a/ELF/Arch/PPC.cpp b/ELF/Arch/PPC.cpp index b5f0d5b4c687..19e10729a00e 100644 --- a/ELF/Arch/PPC.cpp +++ b/ELF/Arch/PPC.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "Error.h" -#include "Memory.h" #include "Symbols.h" #include "Target.h" #include "llvm/Support/Endian.h" @@ -22,7 +21,7 @@ using namespace lld::elf; namespace { class PPC final : public TargetInfo { public: - PPC() {} + PPC() { GotBaseSymOff = 0x8000; } void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const override; @@ -60,4 +59,7 @@ RelExpr PPC::getRelExpr(uint32_t Type, const SymbolBody &S, } } -TargetInfo *elf::createPPCTargetInfo() { return make<PPC>(); } +TargetInfo *elf::getPPCTargetInfo() { + static PPC Target; + return &Target; +} diff --git a/ELF/Arch/PPC64.cpp b/ELF/Arch/PPC64.cpp index eb1e917d5790..bf414d75bec7 100644 --- a/ELF/Arch/PPC64.cpp +++ b/ELF/Arch/PPC64.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "Error.h" -#include "Memory.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -212,4 +211,7 @@ void PPC64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { } } -TargetInfo *elf::createPPC64TargetInfo() { return make<PPC64>(); } +TargetInfo *elf::getPPC64TargetInfo() { + static PPC64 Target; + return &Target; +} diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp index bc0d2b81a613..a1e9bcaf1b12 100644 --- a/ELF/Arch/X86.cpp +++ b/ELF/Arch/X86.cpp @@ -9,7 +9,6 @@ #include "Error.h" #include "InputFiles.h" -#include "Memory.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -47,6 +46,7 @@ public: } // namespace X86::X86() { + GotBaseSymOff = -1; CopyRel = R_386_COPY; GotRel = R_386_GLOB_DAT; PltRel = R_386_JUMP_SLOT; @@ -60,9 +60,7 @@ X86::X86() { PltEntrySize = 16; PltHeaderSize = 16; TlsGdRelaxSkip = 2; - - // 0xCC is the "int3" (call debug exception handler) instruction. - TrapInstr = 0xcccccccc; + TrapInstr = 0xcccccccc; // 0xcc = INT3 } RelExpr X86::getRelExpr(uint32_t Type, const SymbolBody &S, @@ -360,4 +358,7 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const { memcpy(Loc - 2, Inst, sizeof(Inst)); } -TargetInfo *elf::createX86TargetInfo() { return make<X86>(); } +TargetInfo *elf::getX86TargetInfo() { + static X86 Target; + return &Target; +} diff --git a/ELF/Arch/X86_64.cpp b/ELF/Arch/X86_64.cpp index b790868c7125..10179f57ee93 100644 --- a/ELF/Arch/X86_64.cpp +++ b/ELF/Arch/X86_64.cpp @@ -9,7 +9,6 @@ #include "Error.h" #include "InputFiles.h" -#include "Memory.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -52,6 +51,7 @@ private: } // namespace template <class ELFT> X86_64<ELFT>::X86_64() { + GotBaseSymOff = -1; CopyRel = R_X86_64_COPY; GotRel = R_X86_64_GLOB_DAT; PltRel = R_X86_64_JUMP_SLOT; @@ -65,13 +65,11 @@ template <class ELFT> X86_64<ELFT>::X86_64() { PltEntrySize = 16; PltHeaderSize = 16; TlsGdRelaxSkip = 2; + TrapInstr = 0xcccccccc; // 0xcc = INT3 // Align to the large page size (known as a superpage or huge page). // FreeBSD automatically promotes large, superpage-aligned allocations. DefaultImageBase = 0x200000; - - // 0xCC is the "int3" (call debug exception handler) instruction. - TrapInstr = 0xcccccccc; } template <class ELFT> @@ -464,5 +462,12 @@ void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const { write32le(Loc - 1, Val + 1); } -TargetInfo *elf::createX32TargetInfo() { return make<X86_64<ELF32LE>>(); } -TargetInfo *elf::createX86_64TargetInfo() { return make<X86_64<ELF64LE>>(); } +TargetInfo *elf::getX32TargetInfo() { + static X86_64<ELF32LE> Target; + return &Target; +} + +TargetInfo *elf::getX86_64TargetInfo() { + static X86_64<ELF64LE> Target; + return &Target; +} diff --git a/ELF/CMakeLists.txt b/ELF/CMakeLists.txt index 09a19fee14b2..b4bc215a77eb 100644 --- a/ELF/CMakeLists.txt +++ b/ELF/CMakeLists.txt @@ -12,6 +12,7 @@ add_lld_library(lldELF Arch/ARM.cpp Arch/AVR.cpp Arch/Mips.cpp + Arch/MipsArchTree.cpp Arch/PPC.cpp Arch/PPC64.cpp Arch/X86.cpp @@ -29,7 +30,6 @@ add_lld_library(lldELF LinkerScript.cpp MapFile.cpp MarkLive.cpp - Mips.cpp OutputSections.cpp Relocations.cpp ScriptLexer.cpp diff --git a/ELF/Config.h b/ELF/Config.h index 9c73b4c9c068..32e86b0ec7b6 100644 --- a/ELF/Config.h +++ b/ELF/Config.h @@ -70,7 +70,7 @@ struct VersionDefinition { // Structure for mapping renamed symbols struct RenamedSymbol { Symbol *Target; - uint8_t OrigBinding; + uint8_t OriginalBinding; }; // This struct contains the global configuration for the linker. diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index f24c941fe773..5fb33caea46f 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -200,6 +200,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { error("attempted static link of dynamic object " + Path); return; } + // DSOs usually have DT_SONAME tags in their ELF headers, and the // sonames are used to identify DSOs. But if they are missing, // they are identified by filenames. We don't know whether the new @@ -210,8 +211,8 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. - Files.push_back(createSharedFile( - MBRef, WithLOption ? sys::path::filename(Path) : Path)); + Files.push_back( + createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path)); return; default: if (InLib) @@ -301,7 +302,7 @@ static uint64_t getZOptionValue(opt::InputArgList &Args, StringRef Key, for (auto *Arg : Args.filtered(OPT_z)) { std::pair<StringRef, StringRef> KV = StringRef(Arg->getValue()).split('='); if (KV.first == Key) { - uint64_t Result; + uint64_t Result = Default; if (!to_integer(KV.second, Result)) error("invalid " + Key + ": " + KV.second); return Result; @@ -907,12 +908,47 @@ getDefsym(opt::InputArgList &Args) { return Ret; } +// Parses `--exclude-libs=lib,lib,...`. +// The library names may be delimited by commas or colons. +static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) { + DenseSet<StringRef> Ret; + for (auto *Arg : Args.filtered(OPT_exclude_libs)) { + StringRef S = Arg->getValue(); + for (;;) { + size_t Pos = S.find_first_of(",:"); + if (Pos == StringRef::npos) + break; + Ret.insert(S.substr(0, Pos)); + S = S.substr(Pos + 1); + } + Ret.insert(S); + } + return Ret; +} + +// Handles the -exclude-libs option. If a static library file is specified +// by the -exclude-libs option, all public symbols from the archive become +// private unless otherwise specified by version scripts or something. +// A special library name "ALL" means all archive files. +// +// This is not a popular option, but some programs such as bionic libc use it. +static void excludeLibs(opt::InputArgList &Args, ArrayRef<InputFile *> Files) { + DenseSet<StringRef> Libs = getExcludeLibs(Args); + bool All = Libs.count("ALL"); + + for (InputFile *File : Files) + if (auto *F = dyn_cast<ArchiveFile>(File)) + if (All || Libs.count(path::filename(F->getName()))) + for (Symbol *Sym : F->getSymbols()) + Sym->VersionId = VER_NDX_LOCAL; +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { SymbolTable<ELFT> Symtab; elf::Symtab<ELFT>::X = &Symtab; - Target = createTarget(); + Target = getTarget(); Config->MaxPageSize = getMaxPageSize(Args); Config->ImageBase = getImageBase(Args); @@ -958,8 +994,17 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { if (ErrorCount) return; + // Handle the `--undefined <sym>` options. Symtab.scanUndefinedFlags(); + + // Handle undefined symbols in DSOs. Symtab.scanShlibUndefined(); + + // Handle the -exclude-libs option. + if (Args.hasArg(OPT_exclude_libs)) + excludeLibs(Args, Files); + + // Apply version scripts. Symtab.scanVersionScript(); // Create wrapped symbols for -wrap option. diff --git a/ELF/Driver.h b/ELF/Driver.h index af88341632f4..076dda7730ac 100644 --- a/ELF/Driver.h +++ b/ELF/Driver.h @@ -58,7 +58,7 @@ public: // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, -#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, +#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, #include "Options.inc" #undef OPTION }; diff --git a/ELF/DriverUtils.cpp b/ELF/DriverUtils.cpp index f4eadeee9e43..5adb09176a3a 100644 --- a/ELF/DriverUtils.cpp +++ b/ELF/DriverUtils.cpp @@ -42,9 +42,9 @@ using namespace lld::elf; // Create table mapping all options defined in Options.td static const opt::OptTable::Info OptInfo[] = { -#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ - {X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, \ - X8, X7, OPT_##GROUP, OPT_##ALIAS, X6}, +#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ + {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ + X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, #include "Options.inc" #undef OPTION }; diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index 3d11239bf88f..1ff0b4224e70 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -632,8 +632,9 @@ ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File) File(std::move(File)) {} template <class ELFT> void ArchiveFile::parse() { + Symbols.reserve(File->getNumberOfSymbols()); for (const Archive::Symbol &Sym : File->symbols()) - Symtab<ELFT>::X->addLazyArchive(this, Sym); + Symbols.push_back(Symtab<ELFT>::X->addLazyArchive(this, Sym)); } // Returns a buffer pointing to a member file containing a given symbol. diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index 2eec78444837..544a0b009b39 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -251,6 +251,7 @@ public: explicit ArchiveFile(std::unique_ptr<Archive> &&File); static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } template <class ELFT> void parse(); + ArrayRef<Symbol *> getSymbols() { return Symbols; } // Returns a memory buffer for a given symbol and the offset in the archive // for the member. An empty memory buffer and an offset of zero @@ -261,6 +262,7 @@ public: private: std::unique_ptr<Archive> File; llvm::DenseSet<uint64_t> Seen; + std::vector<Symbol *> Symbols; }; class BitcodeFile : public InputFile { diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp index 9aae82bc2992..b1d5e1349460 100644 --- a/ELF/InputSection.cpp +++ b/ELF/InputSection.cpp @@ -399,9 +399,16 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { } } +// The ARM and AArch64 ABI handle pc-relative relocations to undefined weak +// references specially. The general rule is that the value of the symbol in +// this context is the address of the place P. A further special case is that +// branch relocations to an undefined weak reference resolve to the next +// instruction. static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, uint32_t P) { switch (Type) { + // Unresolved branch relocations to weak references resolve to next + // instruction, this will be either 2 or 4 bytes on from P. case R_ARM_THM_JUMP11: return P + 2 + A; case R_ARM_CALL: @@ -415,22 +422,38 @@ static uint32_t getARMUndefinedRelativeWeakVA(uint32_t Type, uint32_t A, case R_ARM_THM_CALL: // We don't want an interworking BLX to ARM return P + 5 + A; - default: + // Unresolved non branch pc-relative relocations + // R_ARM_TARGET2 which can be resolved relatively is not present as it never + // targets a weak-reference. + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_REL32: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: return P + A; } + llvm_unreachable("ARM pc-relative relocation expected\n"); } +// The comment above getARMUndefinedRelativeWeakVA applies to this function. static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, uint64_t P) { switch (Type) { + // Unresolved branch relocations to weak references resolve to next + // instruction, this is 4 bytes on from P. case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: return P + 4 + A; - default: + // Unresolved non branch pc-relative relocations + case R_AARCH64_PREL16: + case R_AARCH64_PREL32: + case R_AARCH64_PREL64: + case R_AARCH64_ADR_PREL_LO21: return P + A; } + llvm_unreachable("AArch64 pc-relative relocation expected\n"); } // ARM SBREL relocations are of the form S + A - B where B is the static base diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index f5a59f0c8c4d..d369a6f978a2 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -338,8 +338,9 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { void LinkerScript::discard(ArrayRef<InputSectionBase *> V) { for (InputSectionBase *S : V) { S->Live = false; - if (S == InX::ShStrTab) - error("discarding .shstrtab section is not allowed"); + if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab || + S == InX::DynStrTab) + error("discarding " + S->Name + " section is not allowed"); discard(S->DependentSections); } } @@ -463,11 +464,6 @@ void LinkerScript::fabricateDefaultCommands() { OSCmd->Sec = Sec; SecToCommand[Sec] = OSCmd; - // Prefer user supplied address over additional alignment constraint - auto I = Config->SectionStartMap.find(Sec->Name); - if (I != Config->SectionStartMap.end()) - OSCmd->AddrExpr = [=] { return I->second; }; - Commands.push_back(OSCmd); if (Sec->Sections.size()) { auto *ISD = make<InputSectionDescription>(""); @@ -953,6 +949,8 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) { template <class ELFT> static void finalizeShtGroup(OutputSection *OS, ArrayRef<InputSection *> Sections) { + assert(Config->Relocatable && Sections.size() == 1); + // sh_link field for SHT_GROUP sections should contain the section index of // the symbol table. OS->Link = InX::SymTab->getParent()->SectionIndex; @@ -960,7 +958,6 @@ static void finalizeShtGroup(OutputSection *OS, // sh_info then contain index of an entry in symbol table section which // provides signature of the section group. elf::ObjectFile<ELFT> *Obj = Sections[0]->getFile<ELFT>(); - assert(Config->Relocatable && Sections.size() == 1); ArrayRef<SymbolBody *> Symbols = Obj->getSymbols(); OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]); } @@ -1044,8 +1041,9 @@ template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) { Sec->Loc = Buf; - // We may have already rendered compressed content when using - // -compress-debug-sections option. Write it together with header. + // If -compress-debug-section is specified and if this is a debug seciton, + // we've already compressed section contents. If that's the case, + // just write it down. if (!Sec->CompressedData.empty()) { memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size()); memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(), @@ -1109,18 +1107,27 @@ ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) { bool LinkerScript::isDefined(StringRef S) { return findSymbol(S) != nullptr; } +static const size_t NoPhdr = -1; + // Returns indices of ELF headers containing specific section. Each index is a // zero based number of ELF header listed within PHDRS {} script block. std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Sec) { if (OutputSectionCommand *Cmd = getCmd(Sec)) { std::vector<size_t> Ret; - for (StringRef PhdrName : Cmd->Phdrs) - Ret.push_back(getPhdrIndex(Cmd->Location, PhdrName)); + for (StringRef PhdrName : Cmd->Phdrs) { + size_t Index = getPhdrIndex(Cmd->Location, PhdrName); + if (Index != NoPhdr) + Ret.push_back(Index); + } return Ret; } return {}; } +// Returns the index of the segment named PhdrName if found otherwise +// NoPhdr. When not found, if PhdrName is not the special case value 'NONE' +// (which can be used to explicitly specify that a section isn't assigned to a +// segment) then error. size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { size_t I = 0; for (PhdrsCommand &Cmd : Opt.PhdrsCommands) { @@ -1128,8 +1135,9 @@ size_t LinkerScript::getPhdrIndex(const Twine &Loc, StringRef PhdrName) { return I; ++I; } - error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); - return 0; + if (PhdrName != "NONE") + error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS"); + return NoPhdr; } template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf); diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp index 0b4a78f8da6b..bde3eefc6d5f 100644 --- a/ELF/MarkLive.cpp +++ b/ELF/MarkLive.cpp @@ -78,7 +78,7 @@ static void resolveReloc(InputSectionBase &Sec, RelT &Rel, typename ELFT::uint Offset = D->Value; if (D->isSection()) Offset += getAddend<ELFT>(Sec, Rel); - Fn({cast<InputSectionBase>(D->Section)->Repl, Offset}); + Fn({cast<InputSectionBase>(D->Section), Offset}); } else if (auto *U = dyn_cast<Undefined>(&B)) { for (InputSectionBase *Sec : CNamedSections.lookup(U->getName())) Fn({Sec, 0}); diff --git a/ELF/Options.td b/ELF/Options.td index 335c7ade6db2..29e14c530c6a 100644 --- a/ELF/Options.td +++ b/ELF/Options.td @@ -92,6 +92,9 @@ def error_limit: S<"error-limit">, def error_unresolved_symbols: F<"error-unresolved-symbols">, HelpText<"Report unresolved symbols as errors">; +def exclude_libs: S<"exclude-libs">, + HelpText<"Exclude static libraries from automatic export">; + def export_dynamic: F<"export-dynamic">, HelpText<"Put symbols in the dynamic symbol table">; @@ -298,6 +301,7 @@ def alias_emit_relocs: Flag<["-"], "q">, Alias<emit_relocs>; def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; def alias_entry_entry: J<"entry=">, Alias<entry>; def alias_error_limit: J<"error-limit=">, Alias<error_limit>; +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>; diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index 6f04a04be8d0..c0bf6b32e6e2 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -273,7 +273,7 @@ void elf::reportDiscarded(InputSectionBase *IS) { if (!Config->PrintGcSections) return; message("removing unused section from '" + IS->Name + "' in file '" + - IS->File->getName()); + IS->File->getName() + "'"); } void OutputSectionFactory::addInputSec(InputSectionBase *IS, @@ -305,7 +305,7 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS, SectionKey Key = createKey(IS, OutsecName); OutputSection *&Sec = Map[Key]; - return addInputSec(IS, OutsecName, Sec); + addInputSec(IS, OutsecName, Sec); } void OutputSectionFactory::addInputSec(InputSectionBase *IS, diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp index 1ac3bce769ee..fd823fe0ed42 100644 --- a/ELF/Relocations.cpp +++ b/ELF/Relocations.cpp @@ -361,7 +361,7 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type, // These expressions always compute a constant if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, - R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, + R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_PC, R_TLSGD, R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E)) return true; diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index a223aec98624..ab8802c86d8e 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -167,8 +167,8 @@ template <class ELFT> void SymbolTable<ELFT>::addSymbolWrap(StringRef Name) { // Tell LTO not to eliminate this symbol Wrap->IsUsedInRegularObj = true; - Config->RenamedSymbols[Real] = RenamedSymbol{Sym, Real->Binding}; - Config->RenamedSymbols[Sym] = RenamedSymbol{Wrap, Sym->Binding}; + Config->RenamedSymbols[Real] = {Sym, Real->Binding}; + Config->RenamedSymbols[Sym] = {Wrap, Sym->Binding}; } // Creates alias for symbol. Used to implement --defsym=ALIAS=SYM. @@ -184,7 +184,7 @@ template <class ELFT> void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, // Tell LTO not to eliminate this symbol Sym->IsUsedInRegularObj = true; - Config->RenamedSymbols[AliasSym] = RenamedSymbol{Sym, AliasSym->Binding}; + Config->RenamedSymbols[AliasSym] = {Sym, AliasSym->Binding}; } // Apply symbol renames created by -wrap and -defsym. The renames are created @@ -193,14 +193,16 @@ template <class ELFT> void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, // symbols are finalized, we can perform the replacement. template <class ELFT> void SymbolTable<ELFT>::applySymbolRenames() { for (auto &KV : Config->RenamedSymbols) { - Symbol *Sym = KV.first; - Symbol *Rename = KV.second.Target; - Sym->Binding = KV.second.OrigBinding; - - // We rename symbols by replacing the old symbol's SymbolBody with the new - // symbol's SymbolBody. This causes all SymbolBody pointers referring to the - // old symbol to instead refer to the new symbol. - memcpy(Sym->Body.buffer, Rename->Body.buffer, sizeof(Sym->Body)); + Symbol *Dst = KV.first; + Symbol *Src = KV.second.Target; + Dst->Binding = KV.second.OriginalBinding; + + // We rename symbols by replacing the old symbol's SymbolBody with + // the new symbol's SymbolBody. The only attribute we want to keep + // is the symbol name, so that two symbols don't have the same name. + StringRef S = Dst->body()->getName(); + memcpy(Dst->Body.buffer, Src->Body.buffer, sizeof(Symbol::Body)); + Dst->body()->setName(S); } } @@ -518,18 +520,18 @@ SymbolBody *SymbolTable<ELFT>::findInCurrentDSO(StringRef Name) { } template <class ELFT> -void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, - const object::Archive::Symbol Sym) { +Symbol *SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, + const object::Archive::Symbol Sym) { Symbol *S; bool WasInserted; StringRef Name = Sym.getName(); std::tie(S, WasInserted) = insert(Name); if (WasInserted) { replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); - return; + return S; } if (!S->body()->isUndefined()) - return; + return S; // Weak undefined symbols should not fetch members from archives. If we were // to keep old symbol we would not know that an archive member was available @@ -540,11 +542,12 @@ void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, // to preserve its type. FIXME: Move the Type field to Symbol. if (S->isWeak()) { replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); - return; + return S; } std::pair<MemoryBufferRef, uint64_t> MBInfo = F->getMember(&Sym); if (!MBInfo.first.getBuffer().empty()) addFile(createObjectFile(MBInfo.first, F->getName(), MBInfo.second)); + return S; } template <class ELFT> diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h index f38d09760c7e..316d9c9bf373 100644 --- a/ELF/SymbolTable.h +++ b/ELF/SymbolTable.h @@ -66,7 +66,7 @@ public: void addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef); - void addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S); + Symbol *addLazyArchive(ArchiveFile *F, const llvm::object::Archive::Symbol S); void addLazyObject(StringRef Name, LazyObjectFile &Obj); Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *File); diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp index 8f9b20477b29..5dce71a32c9c 100644 --- a/ELF/Symbols.cpp +++ b/ELF/Symbols.cpp @@ -35,6 +35,7 @@ DefinedRegular *ElfSym::Edata1; DefinedRegular *ElfSym::Edata2; DefinedRegular *ElfSym::End1; DefinedRegular *ElfSym::End2; +DefinedRegular *ElfSym::GlobalOffsetTable; DefinedRegular *ElfSym::MipsGp; DefinedRegular *ElfSym::MipsGpDisp; DefinedRegular *ElfSym::MipsLocalGp; diff --git a/ELF/Symbols.h b/ELF/Symbols.h index 030527f63744..406fd8e0f57b 100644 --- a/ELF/Symbols.h +++ b/ELF/Symbols.h @@ -69,6 +69,7 @@ public: bool isLocal() const { return IsLocal; } bool isPreemptible() const; StringRef getName() const { return Name; } + void setName(StringRef S) { Name = S; } uint8_t getVisibility() const { return StOther & 0x3; } void parseSymbolVersion(); @@ -317,6 +318,11 @@ struct ElfSym { static DefinedRegular *End1; static DefinedRegular *End2; + // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to + // be at some offset from the base of the .got section, usually 0 or + // the end of the .got. + static DefinedRegular *GlobalOffsetTable; + // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. static DefinedRegular *MipsGp; static DefinedRegular *MipsGpDisp; diff --git a/ELF/Target.cpp b/ELF/Target.cpp index df3f4d6773f0..c1a85e165258 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -47,40 +47,40 @@ std::string lld::toString(uint32_t Type) { return S; } -TargetInfo *elf::createTarget() { +TargetInfo *elf::getTarget() { switch (Config->EMachine) { case EM_386: case EM_IAMCU: - return createX86TargetInfo(); + return getX86TargetInfo(); case EM_AARCH64: - return createAArch64TargetInfo(); + return getAArch64TargetInfo(); case EM_AMDGPU: - return createAMDGPUTargetInfo(); + return getAMDGPUTargetInfo(); case EM_ARM: - return createARMTargetInfo(); + return getARMTargetInfo(); case EM_AVR: - return createAVRTargetInfo(); + return getAVRTargetInfo(); case EM_MIPS: switch (Config->EKind) { case ELF32LEKind: - return createMipsTargetInfo<ELF32LE>(); + return getMipsTargetInfo<ELF32LE>(); case ELF32BEKind: - return createMipsTargetInfo<ELF32BE>(); + return getMipsTargetInfo<ELF32BE>(); case ELF64LEKind: - return createMipsTargetInfo<ELF64LE>(); + return getMipsTargetInfo<ELF64LE>(); case ELF64BEKind: - return createMipsTargetInfo<ELF64BE>(); + return getMipsTargetInfo<ELF64BE>(); default: fatal("unsupported MIPS target"); } case EM_PPC: - return createPPCTargetInfo(); + return getPPCTargetInfo(); case EM_PPC64: - return createPPC64TargetInfo(); + return getPPC64TargetInfo(); case EM_X86_64: if (Config->EKind == ELF32LEKind) - return createX32TargetInfo(); - return createX86_64TargetInfo(); + return getX32TargetInfo(); + return getX86_64TargetInfo(); } fatal("unknown target machine"); } diff --git a/ELF/Target.h b/ELF/Target.h index 79b03f876d0d..bf703fd0086a 100644 --- a/ELF/Target.h +++ b/ELF/Target.h @@ -66,6 +66,10 @@ public: // Given that, the smallest value that can be used in here is 0x10000. uint64_t DefaultImageBase = 0x10000; + // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got section. Use -1 for + // end of .got + uint64_t GotBaseSymOff = 0; + uint32_t CopyRel; uint32_t GotRel; uint32_t PltRel; @@ -102,16 +106,16 @@ public: virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const; }; -TargetInfo *createAArch64TargetInfo(); -TargetInfo *createAMDGPUTargetInfo(); -TargetInfo *createARMTargetInfo(); -TargetInfo *createAVRTargetInfo(); -TargetInfo *createPPC64TargetInfo(); -TargetInfo *createPPCTargetInfo(); -TargetInfo *createX32TargetInfo(); -TargetInfo *createX86TargetInfo(); -TargetInfo *createX86_64TargetInfo(); -template <class ELFT> TargetInfo *createMipsTargetInfo(); +TargetInfo *getAArch64TargetInfo(); +TargetInfo *getAMDGPUTargetInfo(); +TargetInfo *getARMTargetInfo(); +TargetInfo *getAVRTargetInfo(); +TargetInfo *getPPC64TargetInfo(); +TargetInfo *getPPCTargetInfo(); +TargetInfo *getX32TargetInfo(); +TargetInfo *getX86TargetInfo(); +TargetInfo *getX86_64TargetInfo(); +template <class ELFT> TargetInfo *getMipsTargetInfo(); std::string getErrorLocation(const uint8_t *Loc); @@ -119,7 +123,7 @@ uint64_t getPPC64TocBase(); uint64_t getAArch64Page(uint64_t Expr); extern TargetInfo *Target; -TargetInfo *createTarget(); +TargetInfo *getTarget(); template <unsigned N> static void checkInt(uint8_t *Loc, int64_t V, uint32_t Type) { diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index 4ff06388ec78..4c12b18836bf 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -87,6 +87,8 @@ private: uint64_t FileSize; uint64_t SectionHeaderOff; + + bool HasGotBaseSym = false; }; } // anonymous namespace @@ -815,19 +817,13 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { Symtab<ELFT>::X->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_LOCAL); } - // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol - // is magical and is used to produce a R_386_GOTPC relocation. - // The R_386_GOTPC relocation value doesn't actually depend on the - // symbol value, so it could use an index of STN_UNDEF which, according - // to the spec, means the symbol value is 0. - // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in - // the object file. - // The situation is even stranger on x86_64 where the assembly doesn't - // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as - // an undefined symbol in the .o files. - // Given that the symbol is effectively unused, we just create a dummy - // hidden one to avoid the undefined symbol error. - Symtab<ELFT>::X->addIgnored("_GLOBAL_OFFSET_TABLE_"); + // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to + // be at some offset from the base of the .got section, usually 0 or the end + // of the .got + InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot) + : cast<InputSection>(InX::Got); + ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>( + "_GLOBAL_OFFSET_TABLE_", GotSection, Target->GotBaseSymOff); // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For // static linking the linker is required to optimize away any references to @@ -1147,6 +1143,8 @@ static void removeUnusedSyntheticSections(std::vector<OutputSection *> &V) { OutputSection *OS = SS->getParent(); if (!SS->empty() || !OS) continue; + if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable) + continue; OS->Sections.erase(std::find(OS->Sections.begin(), OS->Sections.end(), SS)); SS->Live = false; // If there are no other sections in the output section, remove it from the @@ -1231,6 +1229,13 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) OutputSectionCommands.push_back(Cmd); + // Prefer command line supplied address over other constraints. + for (OutputSectionCommand *Cmd : OutputSectionCommands) { + auto I = Config->SectionStartMap.find(Cmd->Name); + if (I != Config->SectionStartMap.end()) + Cmd->AddrExpr = [=] { return I->second; }; + } + // This is a bit of a hack. A value of 0 means undef, so we set it // to 1 t make __ehdr_start defined. The section number is not // particularly relevant. diff --git a/README.md b/README.md index dc05cdea0a12..38a6b48b1841 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,4 @@ infrastructure project. lld is open source software. You may freely distribute it under the terms of the license agreement found in LICENSE.txt. + diff --git a/docs/windows_support.rst b/docs/windows_support.rst index 72fcbccec149..56df45b32633 100644 --- a/docs/windows_support.rst +++ b/docs/windows_support.rst @@ -49,7 +49,7 @@ Creating DLL Windows resource files support :good:`Done`. If an ``.res`` file is given, LLD converts the file to a COFF - file using ``cvtres.exe`` command and link it. + file using LLVM's Object library. Safe Structured Exception Handler (SEH) :good:`Done` for both x86 and x64. diff --git a/lib/Driver/DarwinLdDriver.cpp b/lib/Driver/DarwinLdDriver.cpp index c859c9802349..f564d8cb8d7e 100644 --- a/lib/Driver/DarwinLdDriver.cpp +++ b/lib/Driver/DarwinLdDriver.cpp @@ -61,9 +61,9 @@ namespace { // Create enum with OPT_xxx values for each option in DarwinLdOptions.td enum { OPT_INVALID = 0, -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELP, META) \ - OPT_##ID, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELP, META, VALUES) \ + OPT_##ID, #include "DarwinLdOptions.inc" #undef OPTION }; @@ -75,10 +75,12 @@ enum { // Create table mapping all options defined in DarwinLdOptions.td static const llvm::opt::OptTable::Info infoTable[] = { -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELPTEXT, METAVAR) \ - { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ - PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS }, +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, #include "DarwinLdOptions.inc" #undef OPTION }; diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 18fb71f16bcf..226a25d3c1ed 100644 --- a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -906,6 +906,7 @@ readCompUnit(const NormalizedFile &normalizedFile, abbrevData.getU8(&abbrevOffset); uint32_t name; llvm::dwarf::Form form; + llvm::DWARFFormParams formParams = {version, addrSize, Format}; TranslationUnitSource tu; while ((name = abbrevData.getULEB128(&abbrevOffset)) | (form = static_cast<llvm::dwarf::Form>( @@ -929,8 +930,7 @@ readCompUnit(const NormalizedFile &normalizedFile, break; } default: - llvm::DWARFFormValue::skipValue(form, infoData, &offset, version, - addrSize, Format); + llvm::DWARFFormValue::skipValue(form, infoData, &offset, formParams); } } return tu; diff --git a/test/COFF/Inputs/associative-comdat-2.s b/test/COFF/Inputs/associative-comdat-2.s new file mode 100644 index 000000000000..cd4ef46539f1 --- /dev/null +++ b/test/COFF/Inputs/associative-comdat-2.s @@ -0,0 +1,13 @@ +# Defines foo and foo_assoc globals. foo is comdat, and foo_assoc is comdat +# associative with it. foo_assoc should be discarded iff foo is discarded, +# either by linker GC or normal comdat merging. + + .section .rdata,"dr",associative,foo + .p2align 3 + .quad foo + + .section .data,"dw",discard,foo + .globl foo # @foo + .p2align 2 +foo: + .long 42 diff --git a/test/COFF/Inputs/pdb1.yaml b/test/COFF/Inputs/pdb1.yaml index 566f2da003c5..90905ae191ec 100644 --- a/test/COFF/Inputs/pdb1.yaml +++ b/test/COFF/Inputs/pdb1.yaml @@ -34,14 +34,10 @@ sections: Records: - Kind: S_GPROC32_ID ProcSym: - PtrParent: 0 - PtrEnd: 0 - PtrNext: 0 CodeSize: 14 DbgStart: 4 DbgEnd: 9 FunctionType: 4101 - Segment: 0 Flags: [ ] DisplayName: main - Kind: S_FRAMEPROC diff --git a/test/COFF/Inputs/pdb_comdat_bar.yaml b/test/COFF/Inputs/pdb_comdat_bar.yaml new file mode 100644 index 000000000000..71a9535c50b7 --- /dev/null +++ b/test/COFF/Inputs/pdb_comdat_bar.yaml @@ -0,0 +1,440 @@ +--- !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\pdb_comdat_bar.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: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 14 + DbgStart: 4 + DbgEnd: 9 + FunctionType: 4102 + Segment: 0 + Flags: [ ] + DisplayName: bar + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 40 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 14 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\pdb_comdat_bar.c' + Lines: + - Offset: 0 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 4 + LineStart: 4 + IsStatement: true + EndDelta: 0 + - Offset: 9 + LineStart: 5 + IsStatement: true + EndDelta: 0 + Columns: + - !Symbols + Records: + - Kind: S_GDATA32 + DataSym: + Type: 116 + DisplayName: global + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\pdb_comdat_bar.c' + Kind: MD5 + Checksum: 365279DB4FCBEDD721BBFC3B14A953C2 + - FileName: 'c:\src\llvm-project\build\foo.h' + Kind: MD5 + Checksum: D74D834EFAC3AE2B45E606A8320B1D5C + - !StringTable + Strings: + - 'c:\src\llvm-project\build\pdb_comdat_bar.c' + - 'c:\src\llvm-project\build\foo.h' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4110 + Relocations: + - VirtualAddress: 168 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 172 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 224 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 228 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 288 + SymbolName: global + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 292 + SymbolName: global + 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_ARGLIST + ArgList: + ArgIndices: [ 0 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 3 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_POINTER + Pointer: + ReferentType: 4097 + Attrs: 65548 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: foo + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 3 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4100 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4101 + Name: bar + - 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 -Z7 -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: [ 4105 ] + - Kind: LF_STRING_ID + StringId: + Id: 4106 + String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: pdb_comdat_bar.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4103, 4104, 4108, 4109, 4107 ] + - Name: .bss + Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: '' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E8000000004883C428C3 + Relocations: + - VirtualAddress: 5 + SymbolName: foo + Type: IMAGE_REL_AMD64_REL32 + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 8B0500000000FFC0890500000000C3 + Relocations: + - VirtualAddress: 2 + SymbolName: global + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 10 + SymbolName: global + Type: IMAGE_REL_AMD64_REL32 + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 15 + DbgStart: 0 + DbgEnd: 14 + FunctionType: 4099 + Segment: 0 + Flags: [ ] + DisplayName: foo + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 15 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\foo.h' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + - Offset: 0 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 14 + LineStart: 4 + IsStatement: true + EndDelta: 0 + Columns: + Relocations: + - VirtualAddress: 44 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECTION + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004420000' + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '000000000E00000000000000' + Relocations: + - VirtualAddress: 0 + SymbolName: '$LN3' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 4 + SymbolName: '$LN3' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 8 + SymbolName: '$unwind$bar' + 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: 460 + NumberOfRelocations: 6 + 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: 628 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .bss + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: global + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '.text$mn' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 14 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 1682752513 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 15 + NumberOfRelocations: 2 + NumberOfLinenumbers: 0 + CheckSum: 1746394828 + Number: 0 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: '.debug$S' + Value: 0 + SectionNumber: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 148 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 6 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: foo + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bar + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '$LN3' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_LABEL + - Name: .xdata + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 264583633 + Number: 0 + - Name: '$unwind$bar' + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .pdata + Value: 0 + SectionNumber: 9 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 361370162 + Number: 0 + - Name: '$pdata$bar' + Value: 0 + SectionNumber: 9 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC +... diff --git a/test/COFF/Inputs/pdb_comdat_main.yaml b/test/COFF/Inputs/pdb_comdat_main.yaml new file mode 100644 index 000000000000..d9019d633415 --- /dev/null +++ b/test/COFF/Inputs/pdb_comdat_main.yaml @@ -0,0 +1,446 @@ +--- !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\pdb_comdat_main.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: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 24 + DbgStart: 4 + DbgEnd: 19 + FunctionType: 4102 + Segment: 0 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 40 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 24 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\pdb_comdat_main.c' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + - Offset: 4 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 9 + LineStart: 4 + IsStatement: true + EndDelta: 0 + - Offset: 14 + LineStart: 5 + IsStatement: true + EndDelta: 0 + - Offset: 19 + LineStart: 6 + IsStatement: true + EndDelta: 0 + Columns: + - !Symbols + Records: + - Kind: S_GDATA32 + DataSym: + Type: 116 + DisplayName: global + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\pdb_comdat_main.c' + Kind: MD5 + Checksum: F969E51BBE373436D81492EB61387F36 + - FileName: 'c:\src\llvm-project\build\foo.h' + Kind: MD5 + Checksum: D74D834EFAC3AE2B45E606A8320B1D5C + - !StringTable + Strings: + - 'c:\src\llvm-project\build\pdb_comdat_main.c' + - 'c:\src\llvm-project\build\foo.h' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4111 + Relocations: + - VirtualAddress: 168 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 172 + 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 + - VirtualAddress: 304 + SymbolName: global + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 308 + SymbolName: global + 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_ARGLIST + ArgList: + ArgIndices: [ 0 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 3 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_POINTER + Pointer: + ReferentType: 4097 + Attrs: 65548 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: foo + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4100 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4101 + Name: main + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: bar + - 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 -Z7 -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: [ 4106 ] + - Kind: LF_STRING_ID + StringId: + Id: 4107 + String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: pdb_comdat_main.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E800000000E800000000B82A0000004883C428C3 + Relocations: + - VirtualAddress: 5 + SymbolName: foo + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 10 + SymbolName: bar + Type: IMAGE_REL_AMD64_REL32 + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 8B0500000000FFC0890500000000C3 + Relocations: + - VirtualAddress: 2 + SymbolName: global + Type: IMAGE_REL_AMD64_REL32 + - VirtualAddress: 10 + SymbolName: global + Type: IMAGE_REL_AMD64_REL32 + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 15 + DbgStart: 0 + DbgEnd: 14 + FunctionType: 4099 + Segment: 0 + Flags: [ ] + DisplayName: foo + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 15 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\foo.h' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + - Offset: 0 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 14 + LineStart: 4 + IsStatement: true + EndDelta: 0 + Columns: + Relocations: + - VirtualAddress: 44 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECTION + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004420000' + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '000000001800000000000000' + 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: 480 + NumberOfRelocations: 6 + 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: 648 + 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: 24 + NumberOfRelocations: 2 + NumberOfLinenumbers: 0 + CheckSum: 492663294 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 15 + NumberOfRelocations: 2 + NumberOfLinenumbers: 0 + CheckSum: 1746394828 + Number: 0 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: '.debug$S' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 148 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 5 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: foo + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: bar + 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: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 264583633 + Number: 0 + - Name: '$unwind$main' + Value: 0 + SectionNumber: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .pdata + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 2942184094 + Number: 0 + - Name: '$pdata$main' + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: global + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/Inputs/pdb_lines_1.yaml b/test/COFF/Inputs/pdb_lines_1.yaml new file mode 100644 index 000000000000..3fbb2a94d45f --- /dev/null +++ b/test/COFF/Inputs/pdb_lines_1.yaml @@ -0,0 +1,480 @@ +--- !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\pdb_lines_1.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: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 19 + DbgStart: 4 + DbgEnd: 14 + FunctionType: 4102 + Segment: 0 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 40 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 19 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\pdb_lines_1.c' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + - Offset: 4 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 9 + LineStart: 4 + IsStatement: true + EndDelta: 0 + - Offset: 14 + LineStart: 5 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\pdb_lines_1.c' + Kind: MD5 + Checksum: 4EB19DCD86C3BA2238A255C718572E7B + - FileName: 'c:\src\llvm-project\build\foo.h' + Kind: MD5 + Checksum: 061EB73ABB642532857A4F1D9CBAC323 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\pdb_lines_1.c' + - 'c:\src\llvm-project\build\foo.h' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4111 + Relocations: + - VirtualAddress: 164 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 168 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 220 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 224 + 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_ARGLIST + ArgList: + ArgIndices: [ ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 3 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_POINTER + Pointer: + ReferentType: 4097 + Attrs: 65548 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: foo + - Kind: LF_ARGLIST + ArgList: + ArgIndices: [ 0 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4100 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4101 + Name: main + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: bar + - 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 -Z7 -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: [ 4106 ] + - Kind: LF_STRING_ID + StringId: + Id: 4107 + String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: pdb_lines_1.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E800000000B82A0000004883C428C3 + Relocations: + - VirtualAddress: 5 + SymbolName: foo + Type: IMAGE_REL_AMD64_REL32 + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 4883EC28E8000000004883C428C3 + Relocations: + - VirtualAddress: 5 + SymbolName: bar + Type: IMAGE_REL_AMD64_REL32 + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 14 + DbgStart: 4 + DbgEnd: 9 + FunctionType: 4099 + Segment: 0 + Flags: [ ] + DisplayName: foo + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 40 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ MarkedInline, AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 14 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\foo.h' + Lines: + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + - Offset: 4 + LineStart: 3 + IsStatement: true + EndDelta: 0 + - Offset: 9 + LineStart: 4 + IsStatement: true + EndDelta: 0 + Columns: + Relocations: + - VirtualAddress: 44 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + SymbolName: foo + Type: IMAGE_REL_AMD64_SECTION + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004420000' + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '000000000E00000000000000' + Relocations: + - VirtualAddress: 0 + SymbolName: '$LN3' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 4 + SymbolName: '$LN3' + Type: IMAGE_REL_AMD64_ADDR32NB + - VirtualAddress: 8 + SymbolName: '$unwind$foo' + Type: IMAGE_REL_AMD64_ADDR32NB + - Name: .xdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '0104010004420000' + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '000000001300000000000000' + 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: 432 + 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: 644 + 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: 19 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 791570821 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 14 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 1682752513 + Number: 0 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: '.debug$S' + Value: 0 + SectionNumber: 6 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 148 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 5 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: bar + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: foo + Value: 0 + SectionNumber: 5 + 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: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_LABEL + - 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: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 264583633 + Number: 5 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: '$unwind$foo' + Value: 0 + SectionNumber: 7 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .pdata + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 361370162 + Number: 5 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: '$pdata$foo' + Value: 0 + SectionNumber: 8 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .xdata + Value: 0 + SectionNumber: 9 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 264583633 + Number: 0 + - Name: '$unwind$main' + Value: 0 + SectionNumber: 9 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: .pdata + Value: 0 + SectionNumber: 10 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 12 + NumberOfRelocations: 3 + NumberOfLinenumbers: 0 + CheckSum: 4063508168 + Number: 0 + - Name: '$pdata$main' + Value: 0 + SectionNumber: 10 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC +... diff --git a/test/COFF/Inputs/pdb_lines_2.yaml b/test/COFF/Inputs/pdb_lines_2.yaml new file mode 100644 index 000000000000..8ad8d062db58 --- /dev/null +++ b/test/COFF/Inputs/pdb_lines_2.yaml @@ -0,0 +1,209 @@ +--- !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\pdb_lines_2.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: + PtrParent: 0 + PtrEnd: 0 + PtrNext: 0 + CodeSize: 1 + DbgStart: 0 + DbgEnd: 0 + FunctionType: 4098 + Segment: 0 + Flags: [ ] + DisplayName: bar + - 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: 1 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\pdb_lines_2.c' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: true + EndDelta: 0 + - Offset: 0 + LineStart: 2 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\pdb_lines_2.c' + Kind: MD5 + Checksum: DF91CB3A2B8D917486574BB50CAC4CC7 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\pdb_lines_2.c' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4106 + Relocations: + - VirtualAddress: 164 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 168 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 220 + SymbolName: bar + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 224 + SymbolName: bar + 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_ARGLIST + ArgList: + ArgIndices: [ ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 3 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: bar + - 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 -Z7 -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: [ 4101 ] + - Kind: LF_STRING_ID + StringId: + Id: 4102 + String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: pdb_lines_2.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4099, 4100, 4104, 4105, 4103 ] + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: C3 +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: 568 + 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: 1 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 40735498 + Number: 0 + - Name: bar + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/associative-comdat.s b/test/COFF/associative-comdat.s new file mode 100644 index 000000000000..dd5419533c16 --- /dev/null +++ b/test/COFF/associative-comdat.s @@ -0,0 +1,46 @@ +# RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t1.obj +# RUN: llvm-mc -triple=x86_64-windows-msvc %S/Inputs/associative-comdat-2.s -filetype=obj -o %t2.obj + +# RUN: lld-link -entry:main %t1.obj %t2.obj -out:%t.gc.exe +# RUN: llvm-readobj -sections %t.gc.exe | FileCheck %s + +# RUN: lld-link -entry:main %t1.obj %t2.obj -opt:noref -out:%t.nogc.exe +# RUN: llvm-readobj -sections %t.nogc.exe | FileCheck %s + +# CHECK: Sections [ +# CHECK: Section { +# CHECK: Number: 1 +# CHECK-LABEL: Name: .data (2E 64 61 74 61 00 00 00) +# CHECK-NEXT: VirtualSize: 0x4 +# CHECK: Section { +# CHECK-LABEL: Name: .rdata (2E 72 64 61 74 61 00 00) +# This is the critical check to show that only *one* definition of +# foo_assoc was retained. This *must* be 8, not 16. +# CHECK-NEXT: VirtualSize: 0x8 + + .text + .def main; + .scl 2; + .type 32; + .endef + .globl main # -- Begin function main + .p2align 4, 0x90 +main: # @main +# BB#0: + movl foo(%rip), %eax + retq + # -- End function + +# Defines foo and foo_assoc globals. foo is comdat, and foo_assoc is comdat +# associative with it. foo_assoc should be discarded iff foo is discarded, +# either by linker GC or normal comdat merging. + + .section .rdata,"dr",associative,foo + .p2align 3 + .quad foo + + .section .data,"dw",discard,foo + .globl foo # @foo + .p2align 2 +foo: + .long 42 diff --git a/test/COFF/def-name.test b/test/COFF/def-name.test index c48424a1bff0..b971007eda37 100644 --- a/test/COFF/def-name.test +++ b/test/COFF/def-name.test @@ -1,5 +1,3 @@ -# REQUIRES: winres - # RUN: rm -rf %t # RUN: mkdir -p %t # RUN: cd %t diff --git a/test/COFF/dll.test b/test/COFF/dll.test index db4b4056552c..abd39f4eeb24 100644 --- a/test/COFF/dll.test +++ b/test/COFF/dll.test @@ -1,5 +1,3 @@ -# REQUIRES: winres - # RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj # RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \ # RUN: /export:mangled diff --git a/test/COFF/dllimport-gc.test b/test/COFF/dllimport-gc.test index 54ae773e793f..d8523fbc7dae 100644 --- a/test/COFF/dllimport-gc.test +++ b/test/COFF/dllimport-gc.test @@ -1,5 +1,3 @@ -# REQUIRES: winres - # RUN: yaml2obj < %p/Inputs/export.yaml > %t-lib.obj # RUN: lld-link /out:%t.dll /dll %t-lib.obj /implib:%t.lib /export:exportfn1 diff --git a/test/COFF/guardcf.test b/test/COFF/guardcf.test new file mode 100644 index 000000000000..4f99d705301c --- /dev/null +++ b/test/COFF/guardcf.test @@ -0,0 +1,74 @@ +# RUN: yaml2obj < %s > %t.obj +# RUN: lld-link /entry:main /out:%t.exe %t.obj + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 000000000000 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 6 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_fids_count + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_fids_table + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_flags + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_iat_count + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_iat_table + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_longjmp_count + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_longjmp_table + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/hello32.test b/test/COFF/hello32.test index 66b52378aaa3..9464a3c114eb 100644 --- a/test/COFF/hello32.test +++ b/test/COFF/hello32.test @@ -21,7 +21,7 @@ HEADER-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2) HEADER-NEXT: ] HEADER-NEXT: } HEADER-NEXT: ImageOptionalHeader { -HEADER-NEXT: MajorLinkerVersion: 0 +HEADER-NEXT: MajorLinkerVersion: 14 HEADER-NEXT: MinorLinkerVersion: 0 HEADER-NEXT: SizeOfCode: 512 HEADER-NEXT: SizeOfInitializedData: 1536 diff --git a/test/COFF/icf-associative.test b/test/COFF/icf-associative.test index 1c63b05d8f22..bfaeabb4d41a 100644 --- a/test/COFF/icf-associative.test +++ b/test/COFF/icf-associative.test @@ -16,7 +16,7 @@ sections: Alignment: 16 SectionData: 4883EC28E8000000004883C428C3 - - Name: '.debug$S' + - Name: '.debug_blah' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: 0000000000000000000000000000 @@ -26,7 +26,7 @@ sections: Alignment: 16 SectionData: 4883EC28E8000000004883C428C3 - - Name: '.debug$S' + - Name: '.debug_blah' Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] Alignment: 1 SectionData: FFFFFFFFFFFFFFFFFFFFFFFFFFFF @@ -46,7 +46,7 @@ symbols: Number: 0 Selection: IMAGE_COMDAT_SELECT_ANY - - Name: '.debug$S' + - Name: '.debug_blah' Value: 0 SectionNumber: 2 SimpleType: IMAGE_SYM_TYPE_NULL @@ -74,7 +74,7 @@ symbols: Number: 0 Selection: IMAGE_COMDAT_SELECT_ANY - - Name: '.debug$S' + - Name: '.debug_blah' Value: 0 SectionNumber: 4 SimpleType: IMAGE_SYM_TYPE_NULL diff --git a/test/COFF/manifestinput.test b/test/COFF/manifestinput.test index 376d404d604c..4eb1730bb0e4 100644 --- a/test/COFF/manifestinput.test +++ b/test/COFF/manifestinput.test @@ -1,4 +1,4 @@ -# REQUIRES: winres +# REQUIRES: win_mt # RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj # RUN: lld-link /out:%t.exe /entry:main \ @@ -8,3 +8,28 @@ CHECK: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> CHECK: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo></assembly> + +# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj +# RUN: lld-link /out:%t.exe /entry:main \ +# RUN: /manifest:embed \ +# RUN: /manifestuac:"level='requireAdministrator'" \ +# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj +# RUN: llvm-readobj -coff-resources -file-headers %t.exe | FileCheck %s \ +# RUN: -check-prefix TEST_EMBED + +TEST_EMBED: ResourceTableRVA: 0x1000 +TEST_EMBED-NEXT: ResourceTableSize: 0x298 +TEST_EMBED-DAG: Resources [ +TEST_EMBED-NEXT: Total Number of Resources: 1 +TEST_EMBED-DAG: Number of String Entries: 0 +TEST_EMBED-NEXT: Number of ID Entries: 1 +TEST_EMBED-NEXT: Type: kRT_MANIFEST (ID 24) [ +TEST_EMBED-NEXT: Table Offset: 0x18 +TEST_EMBED-NEXT: Number of String Entries: 0 +TEST_EMBED-NEXT: Number of ID Entries: 1 +TEST_EMBED-NEXT: Name: (ID 1) [ +TEST_EMBED-NEXT: Table Offset: 0x30 +TEST_EMBED-NEXT: Number of String Entries: 0 +TEST_EMBED-NEXT: Number of ID Entries: 1 +TEST_EMBED-NEXT: Language: (ID 1033) [ +TEST_EMBED-NEXT: Entry Offset: 0x48 diff --git a/test/COFF/noentry.test b/test/COFF/noentry.test index 5e241e46e897..cc02c85e7010 100644 --- a/test/COFF/noentry.test +++ b/test/COFF/noentry.test @@ -1,5 +1,3 @@ -# REQUIRES: winres - # RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj # RUN: lld-link /out:%t.dll /dll %t.obj # RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=ENTRY %s diff --git a/test/COFF/out.test b/test/COFF/out.test index 67b2ef01b711..a7b56145996f 100644 --- a/test/COFF/out.test +++ b/test/COFF/out.test @@ -1,4 +1,3 @@ -# REQUIRES: winres # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj # RUN: mkdir -p %T/out/tmp diff --git a/test/COFF/pdb-comdat.test b/test/COFF/pdb-comdat.test new file mode 100644 index 000000000000..769b630d0e8d --- /dev/null +++ b/test/COFF/pdb-comdat.test @@ -0,0 +1,100 @@ +Consider this example program with an inline function "foo": + +==> foo.h <== +extern int global; +__inline void foo() { + ++global; +} +void bar(); +==> pdb_comdat_main.c <== +#include "foo.h" +int main(void) { + foo(); + bar(); + return 42; +} +==> pdb_comdat_bar.c <== +#include "foo.h" +void bar(void) { + foo(); +} + +Both object files will contain debug info for foo, but only the debug info from +pdb_comdat_main.obj should be included in the PDB. + +RUN: rm -rf %t && mkdir -p %t && cd %t +RUN: yaml2obj %S/Inputs/pdb_comdat_main.yaml -o pdb_comdat_main.obj +RUN: yaml2obj %S/Inputs/pdb_comdat_bar.yaml -o pdb_comdat_bar.obj +RUN: lld-link pdb_comdat_main.obj pdb_comdat_bar.obj -out:t.exe -debug -pdb:t.pdb -nodefaultlib -entry:main +RUN: llvm-pdbutil dump -l -symbols t.pdb | FileCheck %s + +CHECK: Lines +CHECK: ============================================================ +CHECK-LABEL: Mod 0000 | `{{.*}}pdb_comdat_main.obj`: +CHECK: c:\src\llvm-project\build\pdb_comdat_main.c (MD5: F969E51BBE373436D81492EB61387F36) +CHECK: c:\src\llvm-project\build\foo.h (MD5: D74D834EFAC3AE2B45E606A8320B1D5C) +CHECK-LABEL: Mod 0001 | `{{.*}}pdb_comdat_bar.obj`: +CHECK: c:\src\llvm-project\build\pdb_comdat_bar.c (MD5: 365279DB4FCBEDD721BBFC3B14A953C2) +CHECK-NOT: c:\src\llvm-project\build\foo.h +CHECK-LABEL: Mod 0002 | `* Linker *`: + +CHECK: Symbols +CHECK: ============================================================ +CHECK-LABEL: Mod 0000 | `{{.*}}pdb_comdat_main.obj`: +CHECK: - S_OBJNAME [size = 56] sig=0, `C:\src\llvm-project\build\pdb_comdat_main.obj` +CHECK: - 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: - S_GPROC32_ID [size = 44] `main` + FIXME: We need to fill in "end". +CHECK: parent = 0, addr = 0002:0000, code size = 24, end = 0 +CHECK: debug start = 4, debug end = 19, flags = none +CHECK: - S_FRAMEPROC [size = 32] +CHECK: size = 40, 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: - S_END [size = 4] +CHECK: - S_GDATA32 [size = 24] `global` +CHECK: type = 0x0074 (int), addr = 0000:0000 +CHECK: - S_BUILDINFO [size = 8] BuildId = `4106` +CHECK: - S_GPROC32_ID [size = 44] `foo` +CHECK: parent = 0, addr = 0002:0032, code size = 15, end = 0 +CHECK: debug start = 0, debug end = 14, flags = none +CHECK: - 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 = marked inline | has async eh | opt speed +CHECK: - S_END [size = 4] +CHECK-LABEL: Mod 0001 | `{{.*}}pdb_comdat_bar.obj`: +CHECK: - S_OBJNAME [size = 56] sig=0, `C:\src\llvm-project\build\pdb_comdat_bar.obj` +CHECK: - 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: - S_GPROC32_ID [size = 44] `bar` +CHECK: parent = 0, addr = 0002:0048, code size = 14, end = 0 +CHECK: debug start = 4, debug end = 9, flags = none +CHECK: - S_FRAMEPROC [size = 32] +CHECK: size = 40, 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: - S_END [size = 4] +CHECK: - S_GDATA32 [size = 24] `global` +CHECK: type = 0x0074 (int), addr = 0000:0000 +CHECK: - S_BUILDINFO [size = 8] BuildId = `4109` +CHECK-NOT: - S_GPROC32_ID {{.*}} `foo` +CHECK-LABEL: Mod 0002 | `* Linker *`: + +Reorder the object files and verify that the other table is selected. + +RUN: lld-link pdb_comdat_bar.obj pdb_comdat_main.obj -out:t.exe -debug -pdb:t.pdb -nodefaultlib -entry:main +RUN: llvm-pdbutil dump -l t.pdb | FileCheck %s --check-prefix=REORDER + +REORDER-LABEL: Mod 0000 | `{{.*}}pdb_comdat_bar.obj`: +REORDER: c:\src\llvm-project\build\pdb_comdat_bar.c (MD5: 365279DB4FCBEDD721BBFC3B14A953C2) +REORDER: c:\src\llvm-project\build\foo.h (MD5: D74D834EFAC3AE2B45E606A8320B1D5C) +REORDER-LABEL: Mod 0001 | `{{.*}}pdb_comdat_main.obj`: +REORDER: c:\src\llvm-project\build\pdb_comdat_main.c +REORDER-NOT: c:\src\llvm-project\build\foo.h +REORDER-LABEL: Mod 0002 | `* Linker *`: diff --git a/test/COFF/pdb-lib.s b/test/COFF/pdb-lib.s index 073c6f08abf8..47375cc26ff2 100644 --- a/test/COFF/pdb-lib.s +++ b/test/COFF/pdb-lib.s @@ -3,7 +3,7 @@ # RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj # RUN: llvm-lib bar.obj -out:bar.lib # RUN: lld-link -debug -pdb:foo.pdb foo.obj bar.lib -out:foo.exe -entry:main -# RUN: llvm-pdbutil raw -modules %t/foo.pdb | FileCheck %s +# RUN: llvm-pdbutil dump -modules %t/foo.pdb | FileCheck %s # Make sure that the PDB has module descriptors. foo.obj and bar.lib should be # absolute paths, and bar.obj should be the relative path passed to llvm-lib. diff --git a/test/COFF/pdb-safeseh.yaml b/test/COFF/pdb-safeseh.yaml new file mode 100644 index 000000000000..9faa5042924d --- /dev/null +++ b/test/COFF/pdb-safeseh.yaml @@ -0,0 +1,85 @@ +# RUN: yaml2obj %s -o %t.obj +# RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj +# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s + +# There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in +# it in this debug info. This is similar to the relocations in the loadcfg.obj +# file in the MSVC CRT. We need to make sure that our relocation logic matches +# MSVC's for these absolute, linker-provided symbols. + +# CHECK: Mod 0000 | +# CHECK-NEXT: - S_GDATA32 [size = 40] `___safe_se_handler_table` +# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 +# CHECK-NEXT: Mod 0001 | `* Linker *`: + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_I386 + 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_GDATA32 + DataSym: + Type: 34 + DisplayName: ___safe_se_handler_table + - !StringTable + Strings: + Relocations: + - VirtualAddress: 20 + SymbolName: ___safe_se_handler_table + Type: IMAGE_REL_I386_SECREL + - VirtualAddress: 24 + SymbolName: ___safe_se_handler_table + Type: IMAGE_REL_I386_SECTION + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 488D0500000000C3 + Relocations: + - VirtualAddress: 3 + SymbolName: ___safe_se_handler_table + Type: IMAGE_REL_I386_REL32 +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: 372 + NumberOfRelocations: 6 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 1092178131 + Number: 0 + - Name: _main + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: ___safe_se_handler_table + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... + diff --git a/test/COFF/pdb-secrel-absolute.yaml b/test/COFF/pdb-secrel-absolute.yaml new file mode 100644 index 000000000000..d74f07e32b98 --- /dev/null +++ b/test/COFF/pdb-secrel-absolute.yaml @@ -0,0 +1,84 @@ +# RUN: yaml2obj %s -o %t.obj +# RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj +# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s + +# There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in +# it in this debug info. This is similar to the relocations in the loadcfg.obj +# file in the MSVC CRT. We need to make sure that our relocation logic matches +# MSVC's for these absolute, linker-provided symbols. + +# CHECK: Mod 0000 | +# CHECK-NEXT: - S_GDATA32 [size = 36] `__guard_fids_table` +# CHECK-NEXT: type = 0x0022 (unsigned long), addr = 0003:0000 +# CHECK-NEXT: Mod 0001 | `* Linker *`: + +--- !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_GDATA32 + DataSym: + Type: 34 + DisplayName: __guard_fids_table + - !StringTable + Strings: + Relocations: + - VirtualAddress: 20 + SymbolName: __guard_fids_table + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 24 + SymbolName: __guard_fids_table + Type: IMAGE_REL_AMD64_SECTION + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 488D0500000000C3 + Relocations: + - VirtualAddress: 3 + SymbolName: __guard_fids_table + Type: IMAGE_REL_AMD64_REL32 +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: 372 + NumberOfRelocations: 6 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 1092178131 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __guard_fids_table + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/pdb-source-lines.test b/test/COFF/pdb-source-lines.test new file mode 100644 index 000000000000..a630ecb22d62 --- /dev/null +++ b/test/COFF/pdb-source-lines.test @@ -0,0 +1,124 @@ +Test the linker line tables on roughly the following example: + +==> foo.h <== +void bar(void); +inline void foo(void) { + bar(); +} +==> pdb_lines_1.c <== +#include "foo.h" +int main(void) { + foo(); + return 42; +} +==> pdb_lines_2.c <== +void bar(void) { +} + +$ cl -c -Z7 pdb_lines*.c + +RUN: yaml2obj %S/Inputs/pdb_lines_1.yaml -o %t.pdb_lines_1.obj +RUN: yaml2obj %S/Inputs/pdb_lines_2.yaml -o %t.pdb_lines_2.obj +RUN: lld-link -debug -entry:main -nodefaultlib -out:%t.exe -pdb:%t.pdb %t.pdb_lines_1.obj %t.pdb_lines_2.obj +RUN: llvm-pdbutil pdb2yaml -modules -module-files -subsections=lines,fc %t.pdb | FileCheck %s + +CHECK-LABEL: DbiStream: +CHECK-NEXT: VerHeader: V110 +CHECK-NEXT: Age: 1 +CHECK-NEXT: BuildNumber: 0 +CHECK-NEXT: PdbDllVersion: 0 +CHECK-NEXT: PdbDllRbld: 0 +CHECK-NEXT: Flags: 0 +CHECK-NEXT: MachineType: x86 +CHECK-NEXT: Modules: + +CHECK-LABEL: - Module: {{.*}}pdb_lines_1.obj +CHECK-NEXT: ObjFile: {{.*}}pdb_lines_1.obj +CHECK-NEXT: SourceFiles: +CHECK-NEXT: - '{{.*}}pdb_lines_1.c' +CHECK-NEXT: - '{{.*}}foo.h' +CHECK-NEXT: Subsections: +CHECK-NEXT: - !Lines +CHECK-NEXT: CodeSize: 19 +CHECK-NEXT: Flags: [ ] +CHECK-NEXT: RelocOffset: 0 +CHECK-NEXT: RelocSegment: 2 +CHECK-NEXT: Blocks: +CHECK-NEXT: - FileName: '{{.*}}pdb_lines_1.c' +CHECK-NEXT: Lines: +CHECK-NEXT: - Offset: 0 +CHECK-NEXT: LineStart: 2 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: - Offset: 4 +CHECK-NEXT: LineStart: 3 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: - Offset: 9 +CHECK-NEXT: LineStart: 4 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: - Offset: 14 +CHECK-NEXT: LineStart: 5 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: Columns: +CHECK-NEXT: - !FileChecksums +CHECK-NEXT: Checksums: +CHECK-NEXT: - FileName: '{{.*}}pdb_lines_1.c' +CHECK-NEXT: Kind: MD5 +CHECK-NEXT: Checksum: 4EB19DCD86C3BA2238A255C718572E7B +CHECK-NEXT: - FileName: '{{.*}}foo.h' +CHECK-NEXT: Kind: MD5 +CHECK-NEXT: Checksum: 061EB73ABB642532857A4F1D9CBAC323 +CHECK-NEXT: - !Lines +CHECK-NEXT: CodeSize: 14 +CHECK-NEXT: Flags: [ ] +CHECK-NEXT: RelocOffset: 32 +CHECK-NEXT: RelocSegment: 2 +CHECK-NEXT: Blocks: +CHECK-NEXT: - FileName: '{{.*}}foo.h' +CHECK-NEXT: Lines: +CHECK-NEXT: - Offset: 0 +CHECK-NEXT: LineStart: 2 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: - Offset: 4 +CHECK-NEXT: LineStart: 3 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: - Offset: 9 +CHECK-NEXT: LineStart: 4 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: Columns: + +CHECK-LABEL: - Module: {{.*}}pdb_lines_2.obj +CHECK-NEXT: ObjFile: {{.*}}pdb_lines_2.obj +CHECK-NEXT: SourceFiles: +CHECK-NEXT: - '{{.*}}pdb_lines_2.c' +CHECK-NEXT: Subsections: +CHECK-NEXT: - !Lines +CHECK-NEXT: CodeSize: 1 +CHECK-NEXT: Flags: [ ] +CHECK-NEXT: RelocOffset: 48 +CHECK-NEXT: RelocSegment: 2 +CHECK-NEXT: Blocks: +CHECK-NEXT: - FileName: '{{.*}}pdb_lines_2.c' +CHECK-NEXT: Lines: +CHECK-NEXT: - Offset: 0 +CHECK-NEXT: LineStart: 1 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: - Offset: 0 +CHECK-NEXT: LineStart: 2 +CHECK-NEXT: IsStatement: true +CHECK-NEXT: EndDelta: 0 +CHECK-NEXT: Columns: +CHECK-NEXT: - !FileChecksums +CHECK-NEXT: Checksums: +CHECK-NEXT: - FileName: '{{.*}}pdb_lines_2.c' +CHECK-NEXT: Kind: MD5 +CHECK-NEXT: Checksum: DF91CB3A2B8D917486574BB50CAC4CC7 +CHECK-NEXT: - Module: '* Linker *' +CHECK-NEXT: ObjFile: '' diff --git a/test/COFF/pdb-symbol-types.yaml b/test/COFF/pdb-symbol-types.yaml new file mode 100644 index 000000000000..4951aa8be379 --- /dev/null +++ b/test/COFF/pdb-symbol-types.yaml @@ -0,0 +1,344 @@ +# RUN: yaml2obj %s -o %t.obj +# RUN: lld-link %t.obj -nodefaultlib -entry:main -debug -out:%t.exe -pdb:%t.pdb +# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s + +# To regenerate the object file: +# $ cat symbol-types.c +# struct Foo { int x; }; +# typedef struct Foo UDT_Foo; +# UDT_Foo global_foo = {42}; +# int main() { return global_foo.x; } +# $ cl -c -Z7 symbol-types.c + +# Note that the type of 'global' goes from 0x1005 in the object file to 0x1004 +# in the PDB because the LF_FUNC_ID is moved to the id stream. + +# CHECK: Symbols +# CHECK: ============================================================ +# CHECK-LABEL: Mod 0000 | `{{.*}}pdb-symbol-types.yaml.tmp.obj`: +# CHECK: - S_OBJNAME [size = 52] sig=0, `C:\src\llvm-project\build\symbol-types.obj` +# CHECK: - 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: - S_GPROC32_ID [size = 44] `main` +# CHECK: parent = 0, addr = 0002:0000, code size = 7, end = 0 +# CHECK: debug start = 0, debug end = 6, flags = none +# CHECK: - 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: - S_END [size = 4] +# CHECK: - S_GDATA32 [size = 28] `global_foo` +# CHECK: type = 0x1004 (Foo), addr = 0001:0000 +# CHECK: - S_UDT [size = 16] `UDT_Foo` +# CHECK: original type = 0x1004 +# CHECK: - S_UDT [size = 12] `Foo` +# CHECK: original type = 0x1004 +# CHECK: - S_BUILDINFO [size = 8] BuildId = `4106` +# CHECK-LABEL: Mod 0001 | `* Linker *`: + +--- !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\symbol-types.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: 7 + DbgStart: 0 + DbgEnd: 6 + FunctionType: 4098 + 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: 7 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\symbol-types.c' + Lines: + - Offset: 0 + LineStart: 4 + IsStatement: true + EndDelta: 0 + - Offset: 0 + LineStart: 5 + IsStatement: true + EndDelta: 0 + - Offset: 6 + LineStart: 6 + IsStatement: true + EndDelta: 0 + Columns: + - !Symbols + Records: + - Kind: S_GDATA32 + DataSym: + Type: 4101 + DisplayName: global_foo + - Kind: S_UDT + UDTSym: + Type: 4101 + UDTName: UDT_Foo + - Kind: S_UDT + UDTSym: + Type: 4101 + UDTName: Foo + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\symbol-types.c' + Kind: MD5 + Checksum: F833E1A4909FF6FEC5689A664F3BE725 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\symbol-types.c' + - !Symbols + Records: + - Kind: S_BUILDINFO + BuildInfoSym: + BuildId: 4111 + Relocations: + - VirtualAddress: 164 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 168 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 220 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 224 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 284 + SymbolName: global_foo + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 288 + SymbolName: global_foo + 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_ARGLIST + ArgList: + ArgIndices: [ 0 ] + - Kind: LF_PROCEDURE + Procedure: + ReturnType: 116 + CallConv: NearC + Options: [ None ] + ParameterCount: 0 + ArgumentList: 4096 + - Kind: LF_FUNC_ID + FuncId: + ParentScope: 0 + FunctionType: 4097 + Name: main + - Kind: LF_STRUCTURE + Class: + MemberCount: 0 + Options: [ None, ForwardReference, HasUniqueName ] + FieldList: 0 + Name: Foo + UniqueName: '.?AUFoo@@' + DerivationList: 0 + VTableShape: 0 + Size: 0 + - 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: 4100 + Name: Foo + UniqueName: '.?AUFoo@@' + DerivationList: 0 + VTableShape: 0 + Size: 4 + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'c:\src\llvm-project\build\symbol-types.c' + - Kind: LF_UDT_SRC_LINE + UdtSourceLine: + UDT: 4101 + SourceFile: 4102 + LineNumber: 1 + - 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 -Z7 -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: [ 4106 ] + - Kind: LF_STRING_ID + StringId: + Id: 4107 + String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X' + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: symbol-types.c + - Kind: LF_STRING_ID + StringId: + Id: 0 + String: 'C:\src\llvm-project\build\vc140.pdb' + - Kind: LF_BUILDINFO + BuildInfo: + ArgIndices: [ 4104, 4105, 4109, 4110, 4108 ] + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: 2A000000 + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 8B0500000000C3 + Relocations: + - VirtualAddress: 2 + SymbolName: global_foo + Type: IMAGE_REL_AMD64_REL32 +symbols: + - Name: '@comp.id' + Value: 17063575 + SectionNumber: -1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: '@feat.00' + Value: 2147484048 + SectionNumber: -1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - 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: 432 + NumberOfRelocations: 6 + 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: 732 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: .data + Value: 0 + SectionNumber: 4 + 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: 0 + - Name: global_foo + Value: 0 + SectionNumber: 4 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '.text$mn' + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 7 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 3635526833 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 5 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/test/COFF/pdb.test b/test/COFF/pdb.test index c2881669d358..3acb7188df49 100644 --- a/test/COFF/pdb.test +++ b/test/COFF/pdb.test @@ -6,7 +6,7 @@ # RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \ # RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s -# RUN: llvm-pdbutil raw -modules -section-map -section-contribs \ +# RUN: llvm-pdbutil dump -modules -section-map -section-contribs \ # RUN: -types -ids %t.pdb | FileCheck -check-prefix RAW %s # CHECK: MSF: @@ -22,7 +22,7 @@ # CHECK-NEXT: NumStreams: # CHECK-NEXT: FileSize: # CHECK-NEXT: StreamSizes: -# CHECK-NEXT: StreamMap: +# CHECK: StreamMap: # CHECK: PdbStream: # CHECK-NEXT: Age: 1 # CHECK-NEXT: Guid: @@ -119,10 +119,10 @@ RAW: Modules RAW-NEXT: ============================================================ RAW-NEXT: Mod 0000 | Name: `{{.*}}pdb.test.tmp1.obj`: RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`: -RAW-NEXT: debug stream: 9, # files: 0, has ec info: false +RAW-NEXT: debug stream: 9, # files: 1, has ec info: false RAW-NEXT: Mod 0001 | Name: `{{.*}}pdb.test.tmp2.obj`: RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`: -RAW-NEXT: debug stream: 10, # files: 0, has ec info: false +RAW-NEXT: debug stream: 10, # files: 1, has ec info: false RAW-NEXT: Mod 0002 | Name: `* Linker *`: RAW-NEXT: Obj: ``: RAW-NEXT: debug stream: 11, # files: 0, has ec info: false diff --git a/test/COFF/resource.test b/test/COFF/resource.test index 7b6090d89f65..a73a20258201 100644 --- a/test/COFF/resource.test +++ b/test/COFF/resource.test @@ -1,5 +1,3 @@ -# REQUIRES: winres - # RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj # RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res diff --git a/test/COFF/safeseh.test b/test/COFF/safeseh-diag-feat.test index ed928a51350a..ed928a51350a 100644 --- a/test/COFF/safeseh.test +++ b/test/COFF/safeseh-diag-feat.test diff --git a/test/COFF/safeseh.s b/test/COFF/safeseh.s new file mode 100644 index 000000000000..83c15afbf938 --- /dev/null +++ b/test/COFF/safeseh.s @@ -0,0 +1,60 @@ +# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj +# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main +# RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC +# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:ref -entry:main +# RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-GC + +# CHECK-NOGC: LoadConfig [ +# CHECK-NOGC: Size: 0x48 +# CHECK-NOGC: SEHandlerTable: 0x401048 +# CHECK-NOGC: SEHandlerCount: 1 +# CHECK-NOGC: ] +# CHECK-NOGC: SEHTable [ +# CHECK-NOGC-NEXT: 0x402006 +# CHECK-NOGC-NEXT: ] + +# CHECK-GC: LoadConfig [ +# CHECK-GC: Size: 0x48 +# CHECK-GC: SEHandlerTable: 0x0 +# CHECK-GC: SEHandlerCount: 0 +# CHECK-GC: ] +# CHECK-GC-NOT: SEHTable + + + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 1 + + .def _main; + .scl 2; + .type 32; + .endef + .section .text,"xr",one_only,_main + .globl _main +_main: + movl $42, %eax + ret + +# This handler can be GCd, which will make the safeseh table empty, so it should +# appear null. + .def _my_handler; + .scl 3; + .type 32; + .endef + .section .text,"xr",one_only,_my_handler +_my_handler: + ret + +.safeseh _my_handler + + + .section .rdata,"dr" +.globl __load_config_used +__load_config_used: + .long 72 + .fill 60, 1, 0 + .long ___safe_se_handler_table + .long ___safe_se_handler_count diff --git a/test/COFF/secidx-absolute.s b/test/COFF/secidx-absolute.s new file mode 100644 index 000000000000..bfe7136b31d2 --- /dev/null +++ b/test/COFF/secidx-absolute.s @@ -0,0 +1,33 @@ +# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj +# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe +# RUN: llvm-readobj %t.exe -sections -section-data | FileCheck %s + +# Section relocations against absolute symbols resolve to the last real ouput +# section index plus one. + +.text +.global main +main: +ret + +.section .rdata,"dr" +.secidx __guard_fids_table + +# CHECK: Sections [ +# CHECK: Section { +# CHECK: Number: 1 +# CHECK: Name: .rdata (2E 72 64 61 74 61 00 00) +# CHECK: SectionData ( +# CHECK: 0000: 0300 |..| +# CHECK: ) +# CHECK: } +# CHECK: Section { +# CHECK: Number: 2 +# CHECK: Name: .text (2E 74 65 78 74 00 00 00) +# CHECK: VirtualSize: 0x1 +# CHECK: SectionData ( +# CHECK: 0000: C3 |.| +# CHECK: ) +# CHECK: } +# CHECK-NOT: Section +# CHECK: ] diff --git a/test/COFF/secrel-absolute.s b/test/COFF/secrel-absolute.s new file mode 100644 index 000000000000..69b5ab92991b --- /dev/null +++ b/test/COFF/secrel-absolute.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj +# RUN: not lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe 2>&1 | FileCheck %s + +# secrel relocations against absolute symbols are errors. + +# CHECK: SECREL relocation points to a non-regular symbol: __guard_fids_table + +.text +.global main +main: +ret + +.section .rdata,"dr" +.secrel32 __guard_fids_table diff --git a/test/COFF/secrel-common.s b/test/COFF/secrel-common.s new file mode 100644 index 000000000000..0188f6cb9674 --- /dev/null +++ b/test/COFF/secrel-common.s @@ -0,0 +1,41 @@ +# RUN: llvm-mc %s -filetype=obj -triple=x86_64-windows-msvc -o %t.obj +# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe +# RUN: llvm-readobj %t.exe -sections -section-data | FileCheck %s + +# Section relocations against common symbols resolve to .bss. + +# CHECK: Sections [ +# CHECK: Section { +# CHECK: Number: 1 +# CHECK: Name: .bss (2E 62 73 73 00 00 00 00) +# CHECK: VirtualSize: 0x4 +# CHECK: } +# CHECK: Section { +# CHECK: Number: 2 +# CHECK: Name: .rdata (2E 72 64 61 74 61 00 00) +# CHECK: SectionData ( +# CHECK: 0000: 00000000 01000000 |........| +# CHECK: ) +# CHECK: } +# CHECK: Section { +# CHECK: Number: 3 +# CHECK: Name: .text (2E 74 65 78 74 00 00 00) +# CHECK: VirtualSize: 0x1 +# CHECK: SectionData ( +# CHECK: 0000: C3 |.| +# CHECK: ) +# CHECK: } +# CHECK-NOT: Section +# CHECK: ] + +.text +.global main +main: +ret + +.comm common_global,4,2 + +.section .rdata,"dr" +.secrel32 common_global +.secidx common_global +.short 0 diff --git a/test/ELF/Inputs/exclude-libs.s b/test/ELF/Inputs/exclude-libs.s new file mode 100644 index 000000000000..6d05c5e3aa91 --- /dev/null +++ b/test/ELF/Inputs/exclude-libs.s @@ -0,0 +1,3 @@ +.globl fn +fn: + nop diff --git a/test/ELF/arm-gnu-ifunc-plt.s b/test/ELF/arm-gnu-ifunc-plt.s index 2561a4d34bed..efcaee1e9889 100644 --- a/test/ELF/arm-gnu-ifunc-plt.s +++ b/test/ELF/arm-gnu-ifunc-plt.s @@ -61,9 +61,9 @@ // DISASM: $d: // DISASM-NEXT: 11050: c0 0f 00 00 .word 0x00000fc0 // Alignment to 16 byte boundary not strictly necessary on ARM, but harmless -// DISASM-NEXT: 11054: 00 00 00 00 .word 0x00000000 -// DISASM-NEXT: 11058: 00 00 00 00 .word 0x00000000 -// DISASM-NEXT: 1105c: 00 00 00 00 .word 0x00000000 +// DISASM-NEXT: 11054: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 11058: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 1105c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM: $a: // DISASM-NEXT: 11060: 04 c0 9f e5 ldr r12, [pc, #4] // DISASM-NEXT: 11064: 0f c0 8c e0 add r12, r12, pc diff --git a/test/ELF/arm-got-relative.s b/test/ELF/arm-got-relative.s index db76711fe68e..46a3ca97d080 100644 --- a/test/ELF/arm-got-relative.s +++ b/test/ELF/arm-got-relative.s @@ -16,9 +16,9 @@ _start: bx lr .align 2 .LGOT: - // gas implicitly uses (GOT_PREL) for _GLOBAL_OFFSET_TABLE_ in PIC - // llvm-mc needs the (GOT_PREL) suffix or it generates R_ARM_REL32 - .word _GLOBAL_OFFSET_TABLE_(GOT_PREL) - (.LPIC+8) + // gas implicitly uses (R_ARM_BASE_PREL) for _GLOBAL_OFFSET_TABLE_ in PIC + // llvm-mc generates R_ARM_REL32, this will need updating when MC changes + .word _GLOBAL_OFFSET_TABLE_ - (.LPIC+8) .word function(GOT) .globl function @@ -28,17 +28,17 @@ function: bx lr // CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x204C R_ARM_GLOB_DAT function 0x0 +// CHECK-NEXT: 0x2048 R_ARM_GLOB_DAT function 0x0 // CHECK: Name: _GLOBAL_OFFSET_TABLE_ -// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Value: 0x2048 // CHECK-NEXT: Size: // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None // CHECK-NEXT: Other [ // CHECK-NEXT: STV_HIDDEN // CHECK-NEXT: ] -// CHECK-NEXT: Section: Absolute +// CHECK-NEXT: Section: .got // CODE: Disassembly of section .text: // CODE-NEXT: _start: @@ -49,5 +49,5 @@ function: // CODE:$d.1: // (_GLOBAL_OFFSET_TABLE_ = 0x2048) - (0x1008 + 8) 0x1038 // CODE-NEXT: 1010: 38 10 00 00 -// (Got(function) - GotBase = 0x4 -// CODE-NEXT: 1014: 04 00 00 00 +// (Got(function) - GotBase = 0x0 +// CODE-NEXT: 1014: 00 00 00 00 diff --git a/test/ELF/arm-thumb-branch.s b/test/ELF/arm-thumb-branch.s index 4dc0280b22f6..81bf7a3c68a9 100644 --- a/test/ELF/arm-thumb-branch.s +++ b/test/ELF/arm-thumb-branch.s @@ -54,7 +54,7 @@ callee_high: // CHECK-NEXT: 1001c: ff f3 fd 97 b.w #16777210 // CHECK-NEXT: 10020: 3f f3 ff af bgt.w #1048574 // CHECK-NEXT: 10024: 70 47 bx lr -// CHECK-NEXT: 10026: 00 00 movs r0, r0 +// CHECK-NEXT: 10026: // CHECK-NEXT: Disassembly of section .callee2: // CHECK-NEXT: callee_high: // CHECK-NEXT: 10028: 70 47 bx lr diff --git a/test/ELF/arm-thumb-plt-reloc.s b/test/ELF/arm-thumb-plt-reloc.s index 95a6e9e7af79..f9afbb9c0ce1 100644 --- a/test/ELF/arm-thumb-plt-reloc.s +++ b/test/ELF/arm-thumb-plt-reloc.s @@ -30,7 +30,7 @@ _start: // CHECK-NEXT: 11002: 70 47 bx lr // CHECK: func3: // CHECK-NEXT: 11004: 70 47 bx lr -// CHECK-NEXT: 11006: 00 00 movs r0, r0 +// CHECK-NEXT: 11006: d4 d4 // CHECK: _start: // 11008 + 4 -12 = 0x11000 = func1 // CHECK-NEXT: 11008: ff f7 fa ff bl #-12 @@ -49,7 +49,7 @@ _start: // DSOTHUMB-NEXT: 1002: 70 47 bx lr // DSOTHUMB: func3: // DSOTHUMB-NEXT: 1004: 70 47 bx lr -// DSOTHUMB-NEXT: 1006: 00 00 movs r0, r0 +// DSOTHUMB-NEXT: 1006: d4 d4 // DSOTHUMB: _start: // 0x1008 + 0x28 + 4 = 0x1034 = PLT func1 // DSOTHUMB-NEXT: 1008: 00 f0 14 e8 blx #40 diff --git a/test/ELF/defsym.s b/test/ELF/defsym.s index 778180dc9324..253d5d8f408d 100644 --- a/test/ELF/defsym.s +++ b/test/ELF/defsym.s @@ -9,8 +9,6 @@ # RUN: llvm-readobj -t -s %t2 | FileCheck %s # RUN: llvm-objdump -d -print-imm-hex %t2 | FileCheck %s --check-prefix=USE -## In compare with GNU linkers, symbol defined with --defsym does -## not get aliased name in symbol table: # CHECK: Symbol { # CHECK: Name: foo1 # CHECK-NEXT: Value: 0x123 @@ -21,7 +19,7 @@ # CHECK-NEXT: Section: Absolute # CHECK-NEXT: } # CHECK-NEXT: Symbol { -# CHECK-NEXT: Name: foo1 +# CHECK-NEXT: Name: foo2 # CHECK-NEXT: Value: 0x123 # CHECK-NEXT: Size: # CHECK-NEXT: Binding: Global diff --git a/test/ELF/exclude-libs.s b/test/ELF/exclude-libs.s new file mode 100644 index 000000000000..c36081f40e54 --- /dev/null +++ b/test/ELF/exclude-libs.s @@ -0,0 +1,30 @@ +// REQUIRES: x86 + +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +// RUN: %p/Inputs/exclude-libs.s -o %t2.o +// RUN: mkdir -p %t.dir +// RUN: rm -f %t.dir/exc.a +// RUN: llvm-ar rcs %t.dir/exc.a %t2.o + +// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe +// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s + +// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=foo,bar +// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s + +// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a +// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s + +// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo:bar:exc.a +// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s + +// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL +// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s + +// DEFAULT: Name: fn +// EXCLUDE-NOT: Name: fn + +.globl fn +foo: + call fn@PLT diff --git a/test/ELF/global-offset-table-position-aarch64.s b/test/ELF/global-offset-table-position-aarch64.s new file mode 100644 index 000000000000..624e9b516fed --- /dev/null +++ b/test/ELF/global-offset-table-position-aarch64.s @@ -0,0 +1,30 @@ +// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t +// RUN: ld.lld -shared %t -o %t2 +// RUN: llvm-readobj -t %t2 | FileCheck %s +// REQUIRES: aarch64 +.globl a +.type a,@object +.comm a,4,4 + +.globl f +.type f,@function +f: + adrp x0, :got:a + ldr x0, [x0, #:got_lo12:a] + +.global _start +.type _start,@function +_start: + bl f +.data +.long _GLOBAL_OFFSET_TABLE_ - . + +// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11) +// CHECK-NEXT: Value: 0x30090 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local (0x0) +// CHECK-NEXT: Type: None (0x0) +// CHECK-NEXT: Other [ (0x2) +// CHECK-NEXT: STV_HIDDEN (0x2) +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .got diff --git a/test/ELF/global-offset-table-position-arm.s b/test/ELF/global-offset-table-position-arm.s new file mode 100644 index 000000000000..781d8ce5222f --- /dev/null +++ b/test/ELF/global-offset-table-position-arm.s @@ -0,0 +1,35 @@ +// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t +// RUN: ld.lld -shared %t -o %t2 +// RUN: llvm-readobj -t %t2 | FileCheck %s +// REQUIRES: arm + +// The ARM _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got +.globl a +.type a,%object +.comm a,4,4 + +.globl f +.type f,%function +f: + ldr r2, .L1 +.L0: + add r2, pc +.L1: +.word _GLOBAL_OFFSET_TABLE_ - (.L0+4) +.word a(GOT) + +.global _start +.type _start,%function +_start: + bl f +.data + +// CHECK: Name: _GLOBAL_OFFSET_TABLE_ +// CHECK-NEXT: Value: 0x3068 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other [ (0x2) +// CHECK-NEXT: STV_HIDDEN (0x2) +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .got diff --git a/test/ELF/global-offset-table-position-i386.s b/test/ELF/global-offset-table-position-i386.s new file mode 100644 index 000000000000..907105edcff0 --- /dev/null +++ b/test/ELF/global-offset-table-position-i386.s @@ -0,0 +1,31 @@ +// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t +// RUN: ld.lld -shared %t -o %t2 +// RUN: llvm-readobj -t %t2 | FileCheck %s +// REQUIRES: x86 + +// The X86 _GLOBAL_OFFSET_TABLE_ is defined at the end of the .got section. +.globl a +.type a,@object +.comm a,4,4 + +.globl f +.type f,@function +f: +addl $_GLOBAL_OFFSET_TABLE_, %eax +movl a@GOT(%eax), %eax + +.global _start +.type _start,@function +_start: +addl $_GLOBAL_OFFSET_TABLE_, %eax +calll f@PLT + +// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1) +// CHECK-NEXT: Value: 0x306C +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local (0x0) +// CHECK-NEXT: Type: None (0x0) +// CHECK-NEXT: Other [ (0x2) +// CHECK-NEXT: STV_HIDDEN (0x2) +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .got (0xA) diff --git a/test/ELF/global-offset-table-position-mips.s b/test/ELF/global-offset-table-position-mips.s new file mode 100644 index 000000000000..92daed1c7914 --- /dev/null +++ b/test/ELF/global-offset-table-position-mips.s @@ -0,0 +1,33 @@ +// RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t +// RUN: ld.lld -shared %t -o %t2 +// RUN: llvm-readobj -t %t2 | FileCheck %s + +// REQUIRES: mips + +// The Mips _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got + +.globl a +.hidden a +.type a,@object +.comm a,4,4 + +.globl f +.type f,@function +f: + ld $v0,%got_page(a)($gp) + daddiu $v0,$v0,%got_ofst(a) + +.global _start +.type _start,@function +_start: + lw $t0,%call16(f)($gp) + .word _GLOBAL_OFFSET_TABLE_ - . +// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1) +// CHECK-NEXT: Value: 0x20000 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local (0x0) +// CHECK-NEXT: Type: None (0x0) +// CHECK-NEXT: Other [ (0x2) +// CHECK-NEXT: STV_HIDDEN (0x2) +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .got (0x9) diff --git a/test/ELF/global-offset-table-position.s b/test/ELF/global-offset-table-position.s new file mode 100644 index 000000000000..b3317c7edd8b --- /dev/null +++ b/test/ELF/global-offset-table-position.s @@ -0,0 +1,31 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t +// RUN: ld.lld -shared %t -o %t2 +// RUN: llvm-readobj -t %t2 | FileCheck %s +// REQUIRES: x86 + +// The X86_64 _GLOBAL_OFFSET_TABLE_ is defined at the end of the .got section. +.globl a +.type a,@object +.comm a,4,4 + +.globl f +.type f,@function +f: +movq a@GOTPCREL(%rip), %rax + +.global _start +.type _start,@function +_start: +callq f@PLT +.data +.long _GLOBAL_OFFSET_TABLE_ - . + +// CHECK: Name: _GLOBAL_OFFSET_TABLE_ +// CHECK-NEXT: Value: 0x30D8 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None (0x0) +// CHECK-NEXT: Other [ +// CHECK-NEXT: STV_HIDDEN +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .got diff --git a/test/ELF/global_offset_table_shared.s b/test/ELF/global_offset_table_shared.s index 7935925ae2b3..1ebc0110d4d7 100644 --- a/test/ELF/global_offset_table_shared.s +++ b/test/ELF/global_offset_table_shared.s @@ -1,9 +1,14 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t // RUN: ld.lld -shared %t -o %t2 // RUN: llvm-readobj -t %t2 | FileCheck %s -.long _GLOBAL_OFFSET_TABLE_ +.long _GLOBAL_OFFSET_TABLE_ - . // CHECK: Name: _GLOBAL_OFFSET_TABLE_ -// CHECK-NEXT: Value: +// CHECK-NEXT: Value: 0x2060 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other [ (0x2) +// CHECK-NEXT: STV_HIDDEN (0x2) +// CHECK-NEXT: ] +// CHECK-NEXT: Section: .got diff --git a/test/ELF/invalid-z.s b/test/ELF/invalid-z.s new file mode 100644 index 000000000000..a5343c93e677 --- /dev/null +++ b/test/ELF/invalid-z.s @@ -0,0 +1,9 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: not ld.lld %t.o -o %t -z max-page-size 2>&1 | FileCheck %s +# CHECK: invalid max-page-size +# CHECK-NOT: error + +.global _start +_start: + nop diff --git a/test/ELF/linkerscript/discard-section-err.s b/test/ELF/linkerscript/discard-section-err.s new file mode 100644 index 000000000000..5d9955545d92 --- /dev/null +++ b/test/ELF/linkerscript/discard-section-err.s @@ -0,0 +1,23 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# RUN: echo "SECTIONS { /DISCARD/ : { *(.shstrtab) } }" > %t.script +# RUN: not ld.lld -o %t --script %t.script %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=SHSTRTAB %s +# SHSTRTAB: discarding .shstrtab section is not allowed + +# RUN: echo "SECTIONS { /DISCARD/ : { *(.dynamic) } }" > %t.script +# RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=DYNAMIC %s +# DYNAMIC: discarding .dynamic section is not allowed + +# RUN: echo "SECTIONS { /DISCARD/ : { *(.dynsym) } }" > %t.script +# RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=DYNSYM %s +# DYNSYM: discarding .dynsym section is not allowed + +# RUN: echo "SECTIONS { /DISCARD/ : { *(.dynstr) } }" > %t.script +# RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ +# RUN: FileCheck -check-prefix=DYNSTR %s +# DYNSTR: discarding .dynstr section is not allowed diff --git a/test/ELF/linkerscript/sections.s b/test/ELF/linkerscript/sections.s index d5645c303754..dd4b12f42b89 100644 --- a/test/ELF/linkerscript/sections.s +++ b/test/ELF/linkerscript/sections.s @@ -67,12 +67,6 @@ # SEC-SWAP-NAMES: 7 .shstrtab 0000003b {{[0-9a-f]*}} # SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}} -# Attemp to discard .shstrtab section. -# RUN: echo "SECTIONS { /DISCARD/ : { *(.shstrtab) } }" > %t.script -# RUN: not ld.lld -o %t5 --script %t.script %t 2>&1 | \ -# RUN: FileCheck -check-prefix=SEC-DISCARD %s -# SEC-DISCARD: discarding .shstrtab section is not allowed - # Multiple SECTIONS command specifying additional input section descriptions # for the same output section description - input sections are merged into # one output section. diff --git a/test/ELF/linkerscript/segment-none.s b/test/ELF/linkerscript/segment-none.s new file mode 100644 index 000000000000..d54e835a0c22 --- /dev/null +++ b/test/ELF/linkerscript/segment-none.s @@ -0,0 +1,39 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +## Test that section .foo is not placed in any segment when assigned to segment +## NONE in the linker script and segment NONE is not defined. +# RUN: echo "PHDRS {text PT_LOAD;} \ +# RUN: SECTIONS { \ +# RUN: .text : {*(.text .text*)} :text \ +# RUN: .foo : {*(.foo)} :NONE \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck %s + +## Test that section .foo is placed in segment NONE when assigned to segment +## NONE in the linker script and segment NONE is defined. +# RUN: echo "PHDRS {text PT_LOAD; NONE PT_LOAD;} \ +# RUN: SECTIONS { \ +# RUN: .text : {*(.text .text*)} :text \ +# RUN: .foo : {*(.foo)} :NONE \ +# RUN: }" > %t.script +# RUN: ld.lld -o %t --script %t.script %t.o +# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck --check-prefix=DEFINED %s + +# CHECK: Section to Segment mapping: +# CHECK-NEXT: Segment Sections... +# CHECK-NOT: .foo + +# DEFINED: Section to Segment mapping: +# DEFINED-NEXT: Segment Sections... +# DEFINED-NEXT: 00 .text +# DEFINED-NEXT: 01 .foo + +.global _start +_start: + nop + +.section .foo,"a" +foo: + .long 0 diff --git a/test/ELF/linkerscript/ttext-script.s b/test/ELF/linkerscript/ttext-script.s new file mode 100644 index 000000000000..9dcde9bb13c5 --- /dev/null +++ b/test/ELF/linkerscript/ttext-script.s @@ -0,0 +1,11 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { .text 0x200000 : { *(.text) } }" > %t.script +# RUN: ld.lld -T %t.script -Ttext 0x100000 %t.o -o %t +# RUN: llvm-readobj --elf-output-style=GNU -s %t | FileCheck %s + +# CHECK: .text PROGBITS 0000000000100000 + +.global _start +_start: +nop diff --git a/test/ELF/lto/cache.ll b/test/ELF/lto/cache.ll index 55e3a3d6f6cd..6731f522606f 100644 --- a/test/ELF/lto/cache.ll +++ b/test/ELF/lto/cache.ll @@ -12,6 +12,17 @@ ; Two cached objects, plus a timestamp file and "foo", minus the file we removed. ; RUN: ls %t.cache | count 4 +; Create a file of size 64KB. +; RUN: %python -c "print(' ' * 65536)" > %t.cache/llvmcache-foo + +; This should leave the file in place. +; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k -o %t3 %t2.o %t.o +; RUN: ls %t.cache | count 5 + +; This should remove it. +; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=32k -o %t3 %t2.o %t.o +; RUN: ls %t.cache | count 4 + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/test/ELF/lto/wrap-2.ll b/test/ELF/lto/wrap-2.ll index b2e33f83138e..b318b7f65f2d 100644 --- a/test/ELF/lto/wrap-2.ll +++ b/test/ELF/lto/wrap-2.ll @@ -10,8 +10,8 @@ ; CHECK: foo: ; CHECK-NEXT: pushq %rax -; CHECK-NEXT: callq{{.*}}<__wrap_bar> ; CHECK-NEXT: callq{{.*}}<bar> +; CHECK-NEXT: callq{{.*}}<__real_bar> ; Check that bar and __wrap_bar retain their original binding. ; BIND: Name: bar diff --git a/test/ELF/mips-got16-relocatable.s b/test/ELF/mips-got16-relocatable.s index 963efeb4686e..bbacfdbaa682 100644 --- a/test/ELF/mips-got16-relocatable.s +++ b/test/ELF/mips-got16-relocatable.s @@ -15,8 +15,8 @@ # OBJ-NEXT: 00000000: R_MIPS_GOT16 .data # OBJ-NEXT: 4: 27 24 00 00 addiu $4, $25, 0 # OBJ-NEXT: 00000004: R_MIPS_LO16 .data -# OBJ-NEXT: 8: 00 00 00 00 nop -# OBJ-NEXT: c: 00 00 00 00 nop +# OBJ-NEXT: 8: ef ef ef ef <unknown> +# OBJ-NEXT: c: ef ef ef ef <unknown> # OBJ-NEXT: 10: 8f 99 00 00 lw $25, 0($gp) # OBJ-NEXT: 00000010: R_MIPS_GOT16 .data # OBJ-NEXT: 14: 27 24 00 10 addiu $4, $25, 16 @@ -26,8 +26,8 @@ # SO-NEXT: .text: # SO-NEXT: 10000: 8f 99 80 18 lw $25, -32744($gp) # SO-NEXT: 10004: 27 24 00 00 addiu $4, $25, 0 -# SO-NEXT: 10008: 00 00 00 00 nop -# SO-NEXT: 1000c: 00 00 00 00 nop +# SO-NEXT: 10008: ef ef ef ef <unknown> +# SO-NEXT: 1000c: ef ef ef ef <unknown> # SO-NEXT: 10010: 8f 99 80 18 lw $25, -32744($gp) # SO-NEXT: 10014: 27 24 00 10 addiu $4, $25, 16 diff --git a/test/ELF/mips-npic-call-pic-os.s b/test/ELF/mips-npic-call-pic-os.s index 131289e596e8..aea0fa1221dc 100644 --- a/test/ELF/mips-npic-call-pic-os.s +++ b/test/ELF/mips-npic-call-pic-os.s @@ -33,8 +33,8 @@ # CHECK-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> # CHECK-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 # CHECK-NEXT: 20034: 00 00 00 00 nop -# CHECK-NEXT: 20038: 00 00 00 00 nop -# CHECK-NEXT: 2003c: 00 00 00 00 nop +# CHECK-NEXT: 20038: ef ef ef ef <unknown> +# CHECK-NEXT: 2003c: ef ef ef ef <unknown> # CHECK: foo2: # CHECK-NEXT: 20040: 00 00 00 00 nop # CHECK: __LA25Thunk_fpic: @@ -42,14 +42,14 @@ # CHECK-NEXT: 20048: 08 00 80 18 j 131168 <fpic> # CHECK-NEXT: 2004c: 27 39 00 60 addiu $25, $25, 96 # CHECK-NEXT: 20050: 00 00 00 00 nop -# CHECK-NEXT: 20054: 00 00 00 00 nop -# CHECK-NEXT: 20058: 00 00 00 00 nop -# CHECK-NEXT: 2005c: 00 00 00 00 nop +# CHECK-NEXT: 20054: ef ef ef ef <unknown> +# CHECK-NEXT: 20058: ef ef ef ef <unknown> +# CHECK-NEXT: 2005c: ef ef ef ef <unknown> # CHECK: fpic: # CHECK-NEXT: 20060: 00 00 00 00 nop -# CHECK-NEXT: 20064: 00 00 00 00 nop -# CHECK-NEXT: 20068: 00 00 00 00 nop -# CHECK-NEXT: 2006c: 00 00 00 00 nop +# CHECK-NEXT: 20064: ef ef ef ef <unknown> +# CHECK-NEXT: 20068: ef ef ef ef <unknown> +# CHECK-NEXT: 2006c: ef ef ef ef <unknown> # CHECK: fnpic: # CHECK-NEXT: 20070: 00 00 00 00 nop # CHECK-NEXT: Disassembly of section differentos: @@ -93,13 +93,13 @@ # REVERSE-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> # REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 # REVERSE-NEXT: 20034: 00 00 00 00 nop -# REVERSE-NEXT: 20038: 00 00 00 00 nop -# REVERSE-NEXT: 2003c: 00 00 00 00 nop +# REVERSE-NEXT: 20038: ef ef ef ef <unknown> +# REVERSE-NEXT: 2003c: ef ef ef ef <unknown> # REVERSE: foo2: # REVERSE-NEXT: 20040: 00 00 00 00 nop -# REVERSE-NEXT: 20044: 00 00 00 00 nop -# REVERSE-NEXT: 20048: 00 00 00 00 nop -# REVERSE-NEXT: 2004c: 00 00 00 00 nop +# REVERSE-NEXT: 20044: ef ef ef ef <unknown> +# REVERSE-NEXT: 20048: ef ef ef ef <unknown> +# REVERSE-NEXT: 2004c: ef ef ef ef <unknown> # REVERSE: __LA25Thunk_fpic: # REVERSE-NEXT: 20050: 3c 19 00 02 lui $25, 2 # REVERSE-NEXT: 20054: 08 00 80 18 j 131168 <fpic> @@ -107,9 +107,9 @@ # REVERSE-NEXT: 2005c: 00 00 00 00 nop # REVERSE: fpic: # REVERSE-NEXT: 20060: 00 00 00 00 nop -# REVERSE-NEXT: 20064: 00 00 00 00 nop -# REVERSE-NEXT: 20068: 00 00 00 00 nop -# REVERSE-NEXT: 2006c: 00 00 00 00 nop +# REVERSE-NEXT: 20064: ef ef ef ef <unknown> +# REVERSE-NEXT: 20068: ef ef ef ef <unknown> +# REVERSE-NEXT: 2006c: ef ef ef ef <unknown> # REVERSE: fnpic: # REVERSE-NEXT: 20070: 00 00 00 00 nop # REVERSE-NEXT: Disassembly of section differentos: diff --git a/test/ELF/mips-npic-call-pic-script.s b/test/ELF/mips-npic-call-pic-script.s index 6028989ee4cb..230704459463 100644 --- a/test/ELF/mips-npic-call-pic-script.s +++ b/test/ELF/mips-npic-call-pic-script.s @@ -33,77 +33,77 @@ # CHECK-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> # CHECK-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 # CHECK-NEXT: 20034: 00 00 00 00 nop -# CHECK-NEXT: 20038: 00 00 00 00 nop -# CHECK-NEXT: 2003c: 00 00 00 00 nop +# CHECK-NEXT: 20038: ef ef ef ef <unknown> +# CHECK-NEXT: 2003c: ef ef ef ef <unknown> # CHECK: foo2: # CHECK-NEXT: 20040: 00 00 00 00 nop -# CHECK-NEXT: 20044: 00 00 00 00 nop -# CHECK-NEXT: 20048: 00 00 00 00 nop -# CHECK-NEXT: 2004c: 00 00 00 00 nop -# CHECK-NEXT: 20050: 00 00 00 00 nop -# CHECK-NEXT: 20054: 00 00 00 00 nop -# CHECK-NEXT: 20058: 00 00 00 00 nop -# CHECK-NEXT: 2005c: 00 00 00 00 nop -# CHECK-NEXT: 20060: 00 00 00 00 nop -# CHECK-NEXT: 20064: 00 00 00 00 nop -# CHECK-NEXT: 20068: 00 00 00 00 nop -# CHECK-NEXT: 2006c: 00 00 00 00 nop -# CHECK-NEXT: 20070: 00 00 00 00 nop -# CHECK-NEXT: 20074: 00 00 00 00 nop -# CHECK-NEXT: 20078: 00 00 00 00 nop -# CHECK-NEXT: 2007c: 00 00 00 00 nop -# CHECK-NEXT: 20080: 00 00 00 00 nop -# CHECK-NEXT: 20084: 00 00 00 00 nop -# CHECK-NEXT: 20088: 00 00 00 00 nop -# CHECK-NEXT: 2008c: 00 00 00 00 nop -# CHECK-NEXT: 20090: 00 00 00 00 nop -# CHECK-NEXT: 20094: 00 00 00 00 nop -# CHECK-NEXT: 20098: 00 00 00 00 nop -# CHECK-NEXT: 2009c: 00 00 00 00 nop -# CHECK-NEXT: 200a0: 00 00 00 00 nop -# CHECK-NEXT: 200a4: 00 00 00 00 nop -# CHECK-NEXT: 200a8: 00 00 00 00 nop -# CHECK-NEXT: 200ac: 00 00 00 00 nop -# CHECK-NEXT: 200b0: 00 00 00 00 nop -# CHECK-NEXT: 200b4: 00 00 00 00 nop -# CHECK-NEXT: 200b8: 00 00 00 00 nop -# CHECK-NEXT: 200bc: 00 00 00 00 nop -# CHECK-NEXT: 200c0: 00 00 00 00 nop -# CHECK-NEXT: 200c4: 00 00 00 00 nop -# CHECK-NEXT: 200c8: 00 00 00 00 nop -# CHECK-NEXT: 200cc: 00 00 00 00 nop -# CHECK-NEXT: 200d0: 00 00 00 00 nop -# CHECK-NEXT: 200d4: 00 00 00 00 nop -# CHECK-NEXT: 200d8: 00 00 00 00 nop -# CHECK-NEXT: 200dc: 00 00 00 00 nop -# CHECK-NEXT: 200e0: 00 00 00 00 nop -# CHECK-NEXT: 200e4: 00 00 00 00 nop -# CHECK-NEXT: 200e8: 00 00 00 00 nop -# CHECK-NEXT: 200ec: 00 00 00 00 nop -# CHECK-NEXT: 200f0: 00 00 00 00 nop -# CHECK-NEXT: 200f4: 00 00 00 00 nop -# CHECK-NEXT: 200f8: 00 00 00 00 nop -# CHECK-NEXT: 200fc: 00 00 00 00 nop -# CHECK-NEXT: 20100: 00 00 00 00 nop -# CHECK-NEXT: 20104: 00 00 00 00 nop -# CHECK-NEXT: 20108: 00 00 00 00 nop -# CHECK-NEXT: 2010c: 00 00 00 00 nop -# CHECK-NEXT: 20110: 00 00 00 00 nop -# CHECK-NEXT: 20114: 00 00 00 00 nop -# CHECK-NEXT: 20118: 00 00 00 00 nop -# CHECK-NEXT: 2011c: 00 00 00 00 nop -# CHECK-NEXT: 20120: 00 00 00 00 nop -# CHECK-NEXT: 20124: 00 00 00 00 nop -# CHECK-NEXT: 20128: 00 00 00 00 nop -# CHECK-NEXT: 2012c: 00 00 00 00 nop -# CHECK-NEXT: 20130: 00 00 00 00 nop -# CHECK-NEXT: 20134: 00 00 00 00 nop -# CHECK-NEXT: 20138: 00 00 00 00 nop -# CHECK-NEXT: 2013c: 00 00 00 00 nop -# CHECK-NEXT: 20140: 00 00 00 00 nop -# CHECK-NEXT: 20144: 00 00 00 00 nop -# CHECK-NEXT: 20148: 00 00 00 00 nop -# CHECK-NEXT: 2014c: 00 00 00 00 nop +# CHECK-NEXT: 20044: ef ef ef ef <unknown> +# CHECK-NEXT: 20048: ef ef ef ef <unknown> +# CHECK-NEXT: 2004c: ef ef ef ef <unknown> +# CHECK-NEXT: 20050: ef ef ef ef <unknown> +# CHECK-NEXT: 20054: ef ef ef ef <unknown> +# CHECK-NEXT: 20058: ef ef ef ef <unknown> +# CHECK-NEXT: 2005c: ef ef ef ef <unknown> +# CHECK-NEXT: 20060: ef ef ef ef <unknown> +# CHECK-NEXT: 20064: ef ef ef ef <unknown> +# CHECK-NEXT: 20068: ef ef ef ef <unknown> +# CHECK-NEXT: 2006c: ef ef ef ef <unknown> +# CHECK-NEXT: 20070: ef ef ef ef <unknown> +# CHECK-NEXT: 20074: ef ef ef ef <unknown> +# CHECK-NEXT: 20078: ef ef ef ef <unknown> +# CHECK-NEXT: 2007c: ef ef ef ef <unknown> +# CHECK-NEXT: 20080: ef ef ef ef <unknown> +# CHECK-NEXT: 20084: ef ef ef ef <unknown> +# CHECK-NEXT: 20088: ef ef ef ef <unknown> +# CHECK-NEXT: 2008c: ef ef ef ef <unknown> +# CHECK-NEXT: 20090: ef ef ef ef <unknown> +# CHECK-NEXT: 20094: ef ef ef ef <unknown> +# CHECK-NEXT: 20098: ef ef ef ef <unknown> +# CHECK-NEXT: 2009c: ef ef ef ef <unknown> +# CHECK-NEXT: 200a0: ef ef ef ef <unknown> +# CHECK-NEXT: 200a4: ef ef ef ef <unknown> +# CHECK-NEXT: 200a8: ef ef ef ef <unknown> +# CHECK-NEXT: 200ac: ef ef ef ef <unknown> +# CHECK-NEXT: 200b0: ef ef ef ef <unknown> +# CHECK-NEXT: 200b4: ef ef ef ef <unknown> +# CHECK-NEXT: 200b8: ef ef ef ef <unknown> +# CHECK-NEXT: 200bc: ef ef ef ef <unknown> +# CHECK-NEXT: 200c0: ef ef ef ef <unknown> +# CHECK-NEXT: 200c4: ef ef ef ef <unknown> +# CHECK-NEXT: 200c8: ef ef ef ef <unknown> +# CHECK-NEXT: 200cc: ef ef ef ef <unknown> +# CHECK-NEXT: 200d0: ef ef ef ef <unknown> +# CHECK-NEXT: 200d4: ef ef ef ef <unknown> +# CHECK-NEXT: 200d8: ef ef ef ef <unknown> +# CHECK-NEXT: 200dc: ef ef ef ef <unknown> +# CHECK-NEXT: 200e0: ef ef ef ef <unknown> +# CHECK-NEXT: 200e4: ef ef ef ef <unknown> +# CHECK-NEXT: 200e8: ef ef ef ef <unknown> +# CHECK-NEXT: 200ec: ef ef ef ef <unknown> +# CHECK-NEXT: 200f0: ef ef ef ef <unknown> +# CHECK-NEXT: 200f4: ef ef ef ef <unknown> +# CHECK-NEXT: 200f8: ef ef ef ef <unknown> +# CHECK-NEXT: 200fc: ef ef ef ef <unknown> +# CHECK-NEXT: 20100: ef ef ef ef <unknown> +# CHECK-NEXT: 20104: ef ef ef ef <unknown> +# CHECK-NEXT: 20108: ef ef ef ef <unknown> +# CHECK-NEXT: 2010c: ef ef ef ef <unknown> +# CHECK-NEXT: 20110: ef ef ef ef <unknown> +# CHECK-NEXT: 20114: ef ef ef ef <unknown> +# CHECK-NEXT: 20118: ef ef ef ef <unknown> +# CHECK-NEXT: 2011c: ef ef ef ef <unknown> +# CHECK-NEXT: 20120: ef ef ef ef <unknown> +# CHECK-NEXT: 20124: ef ef ef ef <unknown> +# CHECK-NEXT: 20128: ef ef ef ef <unknown> +# CHECK-NEXT: 2012c: ef ef ef ef <unknown> +# CHECK-NEXT: 20130: ef ef ef ef <unknown> +# CHECK-NEXT: 20134: ef ef ef ef <unknown> +# CHECK-NEXT: 20138: ef ef ef ef <unknown> +# CHECK-NEXT: 2013c: ef ef ef ef <unknown> +# CHECK-NEXT: 20140: ef ef ef ef <unknown> +# CHECK-NEXT: 20144: ef ef ef ef <unknown> +# CHECK-NEXT: 20148: ef ef ef ef <unknown> +# CHECK-NEXT: 2014c: ef ef ef ef <unknown> # CHECK: __start: # CHECK-NEXT: 20150: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a> # CHECK-NEXT: 20154: 00 00 00 00 nop @@ -124,9 +124,9 @@ # CHECK-NEXT: 2018c: 00 00 00 00 nop # CHECK: fpic: # CHECK-NEXT: 20190: 00 00 00 00 nop -# CHECK-NEXT: 20194: 00 00 00 00 nop -# CHECK-NEXT: 20198: 00 00 00 00 nop -# CHECK-NEXT: 2019c: 00 00 00 00 nop +# CHECK-NEXT: 20194: ef ef ef ef <unknown> +# CHECK-NEXT: 20198: ef ef ef ef <unknown> +# CHECK-NEXT: 2019c: ef ef ef ef <unknown> # CHECK: fnpic: # CHECK-NEXT: 201a0: 00 00 00 00 nop @@ -166,9 +166,9 @@ __start: # ORPH1-NEXT: 2003c: 00 00 00 00 nop # ORPH1: fpic: # ORPH1-NEXT: 20040: 00 00 00 00 nop -# ORPH1-NEXT: 20044: 00 00 00 00 nop -# ORPH1-NEXT: 20048: 00 00 00 00 nop -# ORPH1-NEXT: 2004c: 00 00 00 00 nop +# ORPH1-NEXT: 20044: ef ef ef ef <unknown> +# ORPH1-NEXT: 20048: ef ef ef ef <unknown> +# ORPH1-NEXT: 2004c: ef ef ef ef <unknown> # ORPH1: fnpic: # ORPH1-NEXT: 20050: 00 00 00 00 nop # ORPH1: __LA25Thunk_foo1a: @@ -181,9 +181,9 @@ __start: # ORPH1-NEXT: 20068: 08 00 80 21 j 131204 <foo1b> # ORPH1-NEXT: 2006c: 27 39 00 84 addiu $25, $25, 132 # ORPH1-NEXT: 20070: 00 00 00 00 nop -# ORPH1-NEXT: 20074: 00 00 00 00 nop -# ORPH1-NEXT: 20078: 00 00 00 00 nop -# ORPH1-NEXT: 2007c: 00 00 00 00 nop +# ORPH1-NEXT: 20074: ef ef ef ef <unknown> +# ORPH1-NEXT: 20078: ef ef ef ef <unknown> +# ORPH1-NEXT: 2007c: ef ef ef ef <unknown> # ORPH1: foo1a: # ORPH1-NEXT: 20080: 00 00 00 00 nop # ORPH1: foo1b: @@ -193,8 +193,8 @@ __start: # ORPH1-NEXT: 2008c: 08 00 80 28 j 131232 <foo2> # ORPH1-NEXT: 20090: 27 39 00 a0 addiu $25, $25, 160 # ORPH1-NEXT: 20094: 00 00 00 00 nop -# ORPH1-NEXT: 20098: 00 00 00 00 nop -# ORPH1-NEXT: 2009c: 00 00 00 00 nop +# ORPH1-NEXT: 20098: ef ef ef ef <unknown> +# ORPH1-NEXT: 2009c: ef ef ef ef <unknown> # ORPH1: foo2: # ORPH1-NEXT: 200a0: 00 00 00 00 nop @@ -224,9 +224,9 @@ __start: # ORPH2-NEXT: 2003c: 00 00 00 00 nop # ORPH2: fpic: # ORPH2-NEXT: 20040: 00 00 00 00 nop -# ORPH2-NEXT: 20044: 00 00 00 00 nop -# ORPH2-NEXT: 20048: 00 00 00 00 nop -# ORPH2-NEXT: 2004c: 00 00 00 00 nop +# ORPH2-NEXT: 20044: ef ef ef ef <unknown> +# ORPH2-NEXT: 20048: ef ef ef ef <unknown> +# ORPH2-NEXT: 2004c: ef ef ef ef <unknown> # ORPH2: fnpic: # ORPH2-NEXT: 20050: 00 00 00 00 nop # ORPH2-NEXT: Disassembly of section .text: @@ -249,7 +249,7 @@ __start: # ORPH2-NEXT: 2008c: 08 00 80 28 j 131232 <foo2> # ORPH2-NEXT: 20090: 27 39 00 a0 addiu $25, $25, 160 # ORPH2-NEXT: 20094: 00 00 00 00 nop -# ORPH2-NEXT: 20098: 00 00 00 00 nop -# ORPH2-NEXT: 2009c: 00 00 00 00 nop +# ORPH2-NEXT: 20098: ef ef ef ef <unknown> +# ORPH2-NEXT: 2009c: ef ef ef ef <unknown> # ORPH2: foo2: # ORPH2-NEXT: 200a0: 00 00 00 00 nop diff --git a/test/ELF/mips-npic-call-pic.s b/test/ELF/mips-npic-call-pic.s index a5a99d719983..c3c94d783410 100644 --- a/test/ELF/mips-npic-call-pic.s +++ b/test/ELF/mips-npic-call-pic.s @@ -51,8 +51,8 @@ # CHECK-NEXT: 2005c: 08 00 80 1c j 131184 <foo2> # CHECK-NEXT: 20060: 27 39 00 70 addiu $25, $25, 112 # CHECK-NEXT: 20064: 00 00 00 00 nop -# CHECK-NEXT: 20068: 00 00 00 00 nop -# CHECK-NEXT: 2006c: 00 00 00 00 nop +# CHECK-NEXT: 20068: ef ef ef ef <unknown> +# CHECK-NEXT: 2006c: ef ef ef ef <unknown> # CHECK: foo2: # CHECK-NEXT: 20070: 00 00 00 00 nop @@ -62,15 +62,15 @@ # CHECK-NEXT: 20078: 08 00 80 24 j 131216 <fpic> # CHECK-NEXT: 2007c: 27 39 00 90 addiu $25, $25, 144 # CHECK-NEXT: 20080: 00 00 00 00 nop -# CHECK-NEXT: 20084: 00 00 00 00 nop -# CHECK-NEXT: 20088: 00 00 00 00 nop -# CHECK-NEXT: 2008c: 00 00 00 00 nop +# CHECK-NEXT: 20084: ef ef ef ef <unknown> +# CHECK-NEXT: 20088: ef ef ef ef <unknown> +# CHECK-NEXT: 2008c: ef ef ef ef <unknown> # CHECK: fpic: # CHECK-NEXT: 20090: 00 00 00 00 nop -# CHECK-NEXT: 20094: 00 00 00 00 nop -# CHECK-NEXT: 20098: 00 00 00 00 nop -# CHECK-NEXT: 2009c: 00 00 00 00 nop +# CHECK-NEXT: 20094: ef ef ef ef <unknown> +# CHECK-NEXT: 20098: ef ef ef ef <unknown> +# CHECK-NEXT: 2009c: ef ef ef ef <unknown> # CHECK: fnpic: # CHECK-NEXT: 200a0: 00 00 00 00 nop @@ -101,13 +101,13 @@ # REVERSE-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> # REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 # REVERSE-NEXT: 20034: 00 00 00 00 nop -# REVERSE-NEXT: 20038: 00 00 00 00 nop -# REVERSE-NEXT: 2003c: 00 00 00 00 nop +# REVERSE-NEXT: 20038: ef ef ef ef <unknown> +# REVERSE-NEXT: 2003c: ef ef ef ef <unknown> # REVERSE: foo2: # REVERSE-NEXT: 20040: 00 00 00 00 nop -# REVERSE-NEXT: 20044: 00 00 00 00 nop -# REVERSE-NEXT: 20048: 00 00 00 00 nop -# REVERSE-NEXT: 2004c: 00 00 00 00 nop +# REVERSE-NEXT: 20044: ef ef ef ef <unknown> +# REVERSE-NEXT: 20048: ef ef ef ef <unknown> +# REVERSE-NEXT: 2004c: ef ef ef ef <unknown> # REVERSE: __start: # REVERSE-NEXT: 20050: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a> # REVERSE-NEXT: 20054: 00 00 00 00 nop @@ -128,9 +128,9 @@ # REVERSE-NEXT: 2008c: 00 00 00 00 nop # REVERSE: fpic: # REVERSE-NEXT: 20090: 00 00 00 00 nop -# REVERSE-NEXT: 20094: 00 00 00 00 nop -# REVERSE-NEXT: 20098: 00 00 00 00 nop -# REVERSE-NEXT: 2009c: 00 00 00 00 nop +# REVERSE-NEXT: 20094: ef ef ef ef <unknown> +# REVERSE-NEXT: 20098: ef ef ef ef <unknown> +# REVERSE-NEXT: 2009c: ef ef ef ef <unknown> # REVERSE: fnpic: # REVERSE-NEXT: 200a0: 00 00 00 00 nop diff --git a/test/ELF/mips-plt-r6.s b/test/ELF/mips-plt-r6.s index ccf233cc73cd..4bab21c32eb9 100644 --- a/test/ELF/mips-plt-r6.s +++ b/test/ELF/mips-plt-r6.s @@ -18,7 +18,7 @@ # # CHECK-NEXT: Disassembly of section .plt: # CHECK-NEXT: .plt: -# CHECK-NEXT: 20010: 3c 1c 00 03 aui $zero, $gp, 3 +# CHECK-NEXT: 20010: 3c 1c 00 03 aui $gp, $zero, 3 # CHECK-NEXT: 20014: 8f 99 00 04 lw $25, 4($gp) # CHECK-NEXT: 20018: 27 9c 00 04 addiu $gp, $gp, 4 # CHECK-NEXT: 2001c: 03 1c c0 23 subu $24, $24, $gp @@ -27,7 +27,7 @@ # CHECK-NEXT: 20028: 03 20 f8 09 jalr $25 # CHECK-NEXT: 2002c: 27 18 ff fe addiu $24, $24, -2 -# CHECK-NEXT: 20030: 3c 0f 00 03 aui $zero, $15, 3 +# CHECK-NEXT: 20030: 3c 0f 00 03 aui $15, $zero, 3 # CHECK-NEXT: 20034: 8d f9 00 0c lw $25, 12($15) # CHECK-NEXT: 20038: 03 20 00 09 jr $25 # CHECK-NEXT: 2003c: 25 f8 00 0c addiu $24, $15, 12 diff --git a/test/ELF/wrap.s b/test/ELF/wrap.s index 17aac2db6e18..d8d802bb8ca4 100644 --- a/test/ELF/wrap.s +++ b/test/ELF/wrap.s @@ -12,6 +12,14 @@ // CHECK-NEXT: movl $0x11010, %edx // CHECK-NEXT: movl $0x11000, %edx +// RUN: llvm-readobj -t -s %t3 | FileCheck -check-prefix=SYM %s +// SYM: Name: __real_foo +// SYM-NEXT: Value: 0x11000 +// SYM: Name: __wrap_foo +// SYM-NEXT: Value: 0x11010 +// SYM: Name: foo +// SYM-NEXT: Value: 0x11010 + .global _start _start: movl $foo, %edx diff --git a/test/lit.cfg b/test/lit.cfg index c8471e1280aa..0cb62d4cab97 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -45,7 +45,7 @@ else: config.test_format = lit.formats.ShTest(execute_external) # suffixes: A list of file extensions to treat as test files. -config.suffixes = ['.ll', '.s', '.objtxt', '.test'] +config.suffixes = ['.ll', '.s', '.test', '.yaml', '.objtxt'] # excludes: A list of directories to exclude from the testsuite. The 'Inputs' # subdirectories contain auxiliary inputs for various tests in their parent @@ -262,8 +262,7 @@ llvm_config_cmd.wait() # Set a fake constant version so that we get consitent output. config.environment['LLD_VERSION'] = 'LLD 1.0' -# Check if Windows resource file compiler exists. -cvtres = lit.util.which('cvtres', config.environment['PATH']) -rc = lit.util.which('rc', config.environment['PATH']) -if cvtres and rc: - config.available_features.add('winres') +# Indirectly check if the mt.exe Microsoft utility exists by searching for +# cvtres, which always accompanies it. +if lit.util.which('cvtres', config.environment['PATH']): + config.available_features.add('win_mt') diff --git a/test/mach-o/executable-exports.yaml b/test/mach-o/executable-exports.yaml index 0b8717eb724e..f16cbd5ce935 100644 --- a/test/mach-o/executable-exports.yaml +++ b/test/mach-o/executable-exports.yaml @@ -42,5 +42,5 @@ global-symbols: ... # CHECK-NOT: _myHidden -# CHECK: 0x00000FFD _myRegular -# CHECK: 0x00000FFE _myWeak [weak_def] +# CHECK: 0x100000FFD _myRegular +# CHECK: 0x100000FFE _myWeak [weak_def] |