| author | |
| committer | |
| log | 95dbba046d84b3e95c63f97d8e6a819b3e1b4cd5 |
| tree | 8ac7dfecb977ce70ec9ebb3b02392f88a74f6833 |
| parent | 7109035b78ee05302bbdaadc52013b430a030b69 |
22 files changed, 371 insertions(+), 31 deletions(-)
deps/lld/COFF/Driver.cpp+3-3| ... | @@ -1551,11 +1551,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | ... | @@ -1551,11 +1551,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1551 | continue; | 1551 | continue; |
| 1552 | } | 1552 | } |
| 1553 | 1553 | ||
| 1554 | // If the symbol isn't common, it must have been replaced with a regular | ||
| 1555 | // symbol, which will carry its own alignment. | ||
| 1554 | auto *DC = dyn_cast<DefinedCommon>(Sym); | 1556 | auto *DC = dyn_cast<DefinedCommon>(Sym); |
| 1555 | if (!DC) { | 1557 | if (!DC) |
| 1556 | warn("/aligncomm symbol " + Name + " of wrong kind"); | ||
| 1557 | continue; | 1558 | continue; |
| 1558 | } | ||
| 1559 | 1559 | ||
| 1560 | CommonChunk *C = DC->getChunk(); | 1560 | CommonChunk *C = DC->getChunk(); |
| 1561 | C->Alignment = std::max(C->Alignment, Alignment); | 1561 | C->Alignment = std::max(C->Alignment, Alignment); |
deps/lld/COFF/InputFiles.cpp+49-5| ... | @@ -205,7 +205,13 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber, | ... | @@ -205,7 +205,13 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber, |
| 205 | 205 | ||
| 206 | void ObjFile::readAssociativeDefinition( | 206 | void ObjFile::readAssociativeDefinition( |
| 207 | COFFSymbolRef Sym, const coff_aux_section_definition *Def) { | 207 | COFFSymbolRef Sym, const coff_aux_section_definition *Def) { |
| 208 | SectionChunk *Parent = SparseChunks[Def->getNumber(Sym.isBigObj())]; | 208 | readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj())); |
| 209 | } | ||
| 210 | |||
| 211 | void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym, | ||
| 212 | const coff_aux_section_definition *Def, | ||
| 213 | uint32_t ParentSection) { | ||
| 214 | SectionChunk *Parent = SparseChunks[ParentSection]; | ||
| 209 | 215 | ||
| 210 | // If the parent is pending, it probably means that its section definition | 216 | // If the parent is pending, it probably means that its section definition |
| 211 | // appears after us in the symbol table. Leave the associated section as | 217 | // appears after us in the symbol table. Leave the associated section as |
| ... | @@ -225,6 +231,35 @@ void ObjFile::readAssociativeDefinition( | ... | @@ -225,6 +231,35 @@ void ObjFile::readAssociativeDefinition( |
| 225 | } | 231 | } |
| 226 | } | 232 | } |
| 227 | 233 | ||
| 234 | void ObjFile::recordPrevailingSymbolForMingw( | ||
| 235 | COFFSymbolRef Sym, DenseMap<StringRef, uint32_t> &PrevailingSectionMap) { | ||
| 236 | // For comdat symbols in executable sections, where this is the copy | ||
| 237 | // of the section chunk we actually include instead of discarding it, | ||
| 238 | // add the symbol to a map to allow using it for implicitly | ||
| 239 | // associating .[px]data$<func> sections to it. | ||
| 240 | int32_t SectionNumber = Sym.getSectionNumber(); | ||
| 241 | SectionChunk *SC = SparseChunks[SectionNumber]; | ||
| 242 | if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) { | ||
| 243 | StringRef Name; | ||
| 244 | COFFObj->getSymbolName(Sym, Name); | ||
| 245 | PrevailingSectionMap[Name] = SectionNumber; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | void ObjFile::maybeAssociateSEHForMingw( | ||
| 250 | COFFSymbolRef Sym, const coff_aux_section_definition *Def, | ||
| 251 | const DenseMap<StringRef, uint32_t> &PrevailingSectionMap) { | ||
| 252 | StringRef Name; | ||
| 253 | COFFObj->getSymbolName(Sym, Name); | ||
| 254 | if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$")) { | ||
| 255 | // For MinGW, treat .[px]data$<func> as implicitly associative to | ||
| 256 | // the symbol <func>. | ||
| 257 | auto ParentSym = PrevailingSectionMap.find(Name); | ||
| 258 | if (ParentSym != PrevailingSectionMap.end()) | ||
| 259 | readAssociativeDefinition(Sym, Def, ParentSym->second); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 228 | Symbol *ObjFile::createRegular(COFFSymbolRef Sym) { | 263 | Symbol *ObjFile::createRegular(COFFSymbolRef Sym) { |
| 229 | SectionChunk *SC = SparseChunks[Sym.getSectionNumber()]; | 264 | SectionChunk *SC = SparseChunks[Sym.getSectionNumber()]; |
| 230 | if (Sym.isExternal()) { | 265 | if (Sym.isExternal()) { |
| ... | @@ -248,19 +283,24 @@ void ObjFile::initializeSymbols() { | ... | @@ -248,19 +283,24 @@ void ObjFile::initializeSymbols() { |
| 248 | std::vector<uint32_t> PendingIndexes; | 283 | std::vector<uint32_t> PendingIndexes; |
| 249 | PendingIndexes.reserve(NumSymbols); | 284 | PendingIndexes.reserve(NumSymbols); |
| 250 | 285 | ||
| 286 | DenseMap<StringRef, uint32_t> PrevailingSectionMap; | ||
| 251 | std::vector<const coff_aux_section_definition *> ComdatDefs( | 287 | std::vector<const coff_aux_section_definition *> ComdatDefs( |
| 252 | COFFObj->getNumberOfSections() + 1); | 288 | COFFObj->getNumberOfSections() + 1); |
| 253 | 289 | ||
| 254 | for (uint32_t I = 0; I < NumSymbols; ++I) { | 290 | for (uint32_t I = 0; I < NumSymbols; ++I) { |
| 255 | COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I)); | 291 | COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I)); |
| 292 | bool PrevailingComdat; | ||
| 256 | if (COFFSym.isUndefined()) { | 293 | if (COFFSym.isUndefined()) { |
| 257 | Symbols[I] = createUndefined(COFFSym); | 294 | Symbols[I] = createUndefined(COFFSym); |
| 258 | } else if (COFFSym.isWeakExternal()) { | 295 | } else if (COFFSym.isWeakExternal()) { |
| 259 | Symbols[I] = createUndefined(COFFSym); | 296 | Symbols[I] = createUndefined(COFFSym); |
| 260 | uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex; | 297 | uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex; |
| 261 | WeakAliases.emplace_back(Symbols[I], TagIndex); | 298 | WeakAliases.emplace_back(Symbols[I], TagIndex); |
| 262 | } else if (Optional<Symbol *> OptSym = createDefined(COFFSym, ComdatDefs)) { | 299 | } else if (Optional<Symbol *> OptSym = |
| 300 | createDefined(COFFSym, ComdatDefs, PrevailingComdat)) { | ||
| 263 | Symbols[I] = *OptSym; | 301 | Symbols[I] = *OptSym; |
| 302 | if (Config->MinGW && PrevailingComdat) | ||
| 303 | recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap); | ||
| 264 | } else { | 304 | } else { |
| 265 | // createDefined() returns None if a symbol belongs to a section that | 305 | // createDefined() returns None if a symbol belongs to a section that |
| 266 | // was pending at the point when the symbol was read. This can happen in | 306 | // was pending at the point when the symbol was read. This can happen in |
| ... | @@ -278,9 +318,12 @@ void ObjFile::initializeSymbols() { | ... | @@ -278,9 +318,12 @@ void ObjFile::initializeSymbols() { |
| 278 | 318 | ||
| 279 | for (uint32_t I : PendingIndexes) { | 319 | for (uint32_t I : PendingIndexes) { |
| 280 | COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); | 320 | COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); |
| 281 | if (auto *Def = Sym.getSectionDefinition()) | 321 | if (auto *Def = Sym.getSectionDefinition()) { |
| 282 | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) | 322 | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) |
| 283 | readAssociativeDefinition(Sym, Def); | 323 | readAssociativeDefinition(Sym, Def); |
| 324 | else if (Config->MinGW) | ||
| 325 | maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap); | ||
| 326 | } | ||
| 284 | if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) { | 327 | if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) { |
| 285 | StringRef Name; | 328 | StringRef Name; |
| 286 | COFFObj->getSymbolName(Sym, Name); | 329 | COFFObj->getSymbolName(Sym, Name); |
| ... | @@ -306,7 +349,9 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) { | ... | @@ -306,7 +349,9 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) { |
| 306 | 349 | ||
| 307 | Optional<Symbol *> ObjFile::createDefined( | 350 | Optional<Symbol *> ObjFile::createDefined( |
| 308 | COFFSymbolRef Sym, | 351 | COFFSymbolRef Sym, |
| 309 | std::vector<const coff_aux_section_definition *> &ComdatDefs) { | 352 | std::vector<const coff_aux_section_definition *> &ComdatDefs, |
| 353 | bool &Prevailing) { | ||
| 354 | Prevailing = false; | ||
| 310 | auto GetName = [&]() { | 355 | auto GetName = [&]() { |
| 311 | StringRef S; | 356 | StringRef S; |
| 312 | COFFObj->getSymbolName(Sym, S); | 357 | COFFObj->getSymbolName(Sym, S); |
| ... | @@ -352,7 +397,6 @@ Optional<Symbol *> ObjFile::createDefined( | ... | @@ -352,7 +397,6 @@ Optional<Symbol *> ObjFile::createDefined( |
| 352 | if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) { | 397 | if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) { |
| 353 | ComdatDefs[SectionNumber] = nullptr; | 398 | ComdatDefs[SectionNumber] = nullptr; |
| 354 | Symbol *Leader; | 399 | Symbol *Leader; |
| 355 | bool Prevailing; | ||
| 356 | if (Sym.isExternal()) { | 400 | if (Sym.isExternal()) { |
| 357 | std::tie(Leader, Prevailing) = | 401 | std::tie(Leader, Prevailing) = |
| 358 | Symtab->addComdat(this, GetName(), Sym.getGeneric()); | 402 | Symtab->addComdat(this, GetName(), Sym.getGeneric()); |
deps/lld/COFF/InputFiles.h+16-1| ... | @@ -13,6 +13,7 @@ | ... | @@ -13,6 +13,7 @@ |
| 13 | #include "Config.h" | 13 | #include "Config.h" |
| 14 | #include "lld/Common/LLVM.h" | 14 | #include "lld/Common/LLVM.h" |
| 15 | #include "llvm/ADT/ArrayRef.h" | 15 | #include "llvm/ADT/ArrayRef.h" |
| 16 | #include "llvm/ADT/DenseMap.h" | ||
| 16 | #include "llvm/ADT/DenseSet.h" | 17 | #include "llvm/ADT/DenseSet.h" |
| 17 | #include "llvm/LTO/LTO.h" | 18 | #include "llvm/LTO/LTO.h" |
| 18 | #include "llvm/Object/Archive.h" | 19 | #include "llvm/Object/Archive.h" |
| ... | @@ -157,10 +158,24 @@ private: | ... | @@ -157,10 +158,24 @@ private: |
| 157 | COFFSymbolRef COFFSym, | 158 | COFFSymbolRef COFFSym, |
| 158 | const llvm::object::coff_aux_section_definition *Def); | 159 | const llvm::object::coff_aux_section_definition *Def); |
| 159 | 160 | ||
| 161 | void readAssociativeDefinition( | ||
| 162 | COFFSymbolRef COFFSym, | ||
| 163 | const llvm::object::coff_aux_section_definition *Def, | ||
| 164 | uint32_t ParentSection); | ||
| 165 | |||
| 166 | void recordPrevailingSymbolForMingw( | ||
| 167 | COFFSymbolRef COFFSym, | ||
| 168 | llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap); | ||
| 169 | |||
| 170 | void maybeAssociateSEHForMingw( | ||
| 171 | COFFSymbolRef Sym, const llvm::object::coff_aux_section_definition *Def, | ||
| 172 | const llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap); | ||
| 173 | |||
| 160 | llvm::Optional<Symbol *> | 174 | llvm::Optional<Symbol *> |
| 161 | createDefined(COFFSymbolRef Sym, | 175 | createDefined(COFFSymbolRef Sym, |
| 162 | std::vector<const llvm::object::coff_aux_section_definition *> | 176 | std::vector<const llvm::object::coff_aux_section_definition *> |
| 163 | &ComdatDefs); | 177 | &ComdatDefs, |
| 178 | bool &PrevailingComdat); | ||
| 164 | Symbol *createRegular(COFFSymbolRef Sym); | 179 | Symbol *createRegular(COFFSymbolRef Sym); |
| 165 | Symbol *createUndefined(COFFSymbolRef Sym); | 180 | Symbol *createUndefined(COFFSymbolRef Sym); |
| 166 | 181 |
deps/lld/ELF/LinkerScript.cpp+13-9| ... | @@ -116,7 +116,8 @@ void LinkerScript::expandMemoryRegions(uint64_t Size) { | ... | @@ -116,7 +116,8 @@ void LinkerScript::expandMemoryRegions(uint64_t Size) { |
| 116 | if (Ctx->MemRegion) | 116 | if (Ctx->MemRegion) |
| 117 | expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name, | 117 | expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name, |
| 118 | Ctx->OutSec->Name); | 118 | Ctx->OutSec->Name); |
| 119 | if (Ctx->LMARegion) | 119 | // Only expand the LMARegion if it is different from MemRegion. |
| 120 | if (Ctx->LMARegion && Ctx->MemRegion != Ctx->LMARegion) | ||
| 120 | expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name, | 121 | expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name, |
| 121 | Ctx->OutSec->Name); | 122 | Ctx->OutSec->Name); |
| 122 | } | 123 | } |
| ... | @@ -750,6 +751,13 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) { | ... | @@ -750,6 +751,13 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) { |
| 750 | return nullptr; | 751 | return nullptr; |
| 751 | } | 752 | } |
| 752 | 753 | ||
| 754 | static OutputSection *findFirstSection(PhdrEntry *Load) { | ||
| 755 | for (OutputSection *Sec : OutputSections) | ||
| 756 | if (Sec->PtLoad == Load) | ||
| 757 | return Sec; | ||
| 758 | return nullptr; | ||
| 759 | } | ||
| 760 | |||
| 753 | // This function assigns offsets to input sections and an output section | 761 | // This function assigns offsets to input sections and an output section |
| 754 | // for a single sections command (e.g. ".text { *(.text); }"). | 762 | // for a single sections command (e.g. ".text { *(.text); }"). |
| 755 | void LinkerScript::assignOffsets(OutputSection *Sec) { | 763 | void LinkerScript::assignOffsets(OutputSection *Sec) { |
| ... | @@ -775,8 +783,11 @@ void LinkerScript::assignOffsets(OutputSection *Sec) { | ... | @@ -775,8 +783,11 @@ void LinkerScript::assignOffsets(OutputSection *Sec) { |
| 775 | // will set the LMA such that the difference between VMA and LMA for the | 783 | // will set the LMA such that the difference between VMA and LMA for the |
| 776 | // section is the same as the preceding output section in the same region | 784 | // section is the same as the preceding output section in the same region |
| 777 | // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html | 785 | // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html |
| 786 | // This, however, should only be done by the first "non-header" section | ||
| 787 | // in the segment. | ||
| 778 | if (PhdrEntry *L = Ctx->OutSec->PtLoad) | 788 | if (PhdrEntry *L = Ctx->OutSec->PtLoad) |
| 779 | L->LMAOffset = Ctx->LMAOffset; | 789 | if (Sec == findFirstSection(L)) |
| 790 | L->LMAOffset = Ctx->LMAOffset; | ||
| 780 | 791 | ||
| 781 | // We can call this method multiple times during the creation of | 792 | // We can call this method multiple times during the creation of |
| 782 | // thunks and want to start over calculation each time. | 793 | // thunks and want to start over calculation each time. |
| ... | @@ -953,13 +964,6 @@ void LinkerScript::adjustSectionsAfterSorting() { | ... | @@ -953,13 +964,6 @@ void LinkerScript::adjustSectionsAfterSorting() { |
| 953 | } | 964 | } |
| 954 | } | 965 | } |
| 955 | 966 | ||
| 956 | static OutputSection *findFirstSection(PhdrEntry *Load) { | ||
| 957 | for (OutputSection *Sec : OutputSections) | ||
| 958 | if (Sec->PtLoad == Load) | ||
| 959 | return Sec; | ||
| 960 | return nullptr; | ||
| 961 | } | ||
| 962 | |||
| 963 | static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) { | 967 | static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) { |
| 964 | // If there is no SECTIONS or if the linkerscript is explicit about program | 968 | // If there is no SECTIONS or if the linkerscript is explicit about program |
| 965 | // headers, do our best to allocate them. | 969 | // headers, do our best to allocate them. |
deps/lld/ELF/SyntheticSections.cpp+3-1| ... | @@ -2929,8 +2929,10 @@ void elf::mergeSections() { | ... | @@ -2929,8 +2929,10 @@ void elf::mergeSections() { |
| 2929 | 2929 | ||
| 2930 | // We do not want to handle sections that are not alive, so just remove | 2930 | // We do not want to handle sections that are not alive, so just remove |
| 2931 | // them instead of trying to merge. | 2931 | // them instead of trying to merge. |
| 2932 | if (!MS->Live) | 2932 | if (!MS->Live) { |
| 2933 | S = nullptr; | ||
| 2933 | continue; | 2934 | continue; |
| 2935 | } | ||
| 2934 | 2936 | ||
| 2935 | StringRef OutsecName = getOutputSectionName(MS); | 2937 | StringRef OutsecName = getOutputSectionName(MS); |
| 2936 | uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize); | 2938 | uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize); |
deps/lld/ELF/Writer.cpp+7-5| ... | @@ -1815,12 +1815,14 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { | ... | @@ -1815,12 +1815,14 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { |
| 1815 | // Segments are contiguous memory regions that has the same attributes | 1815 | // Segments are contiguous memory regions that has the same attributes |
| 1816 | // (e.g. executable or writable). There is one phdr for each segment. | 1816 | // (e.g. executable or writable). There is one phdr for each segment. |
| 1817 | // Therefore, we need to create a new phdr when the next section has | 1817 | // Therefore, we need to create a new phdr when the next section has |
| 1818 | // different flags or is loaded at a discontiguous address using AT linker | 1818 | // different flags or is loaded at a discontiguous address or memory |
| 1819 | // script command. At the same time, we don't want to create a separate | 1819 | // region using AT or AT> linker script command, respectively. At the same |
| 1820 | // load segment for the headers, even if the first output section has | 1820 | // time, we don't want to create a separate load segment for the headers, |
| 1821 | // an AT attribute. | 1821 | // even if the first output section has an AT or AT> attribute. |
| 1822 | uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); | 1822 | uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); |
| 1823 | if ((Sec->LMAExpr && Load->LastSec != Out::ProgramHeaders) || | 1823 | if (((Sec->LMAExpr || |
| 1824 | (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) && | ||
| 1825 | Load->LastSec != Out::ProgramHeaders) || | ||
| 1824 | Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) { | 1826 | Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) { |
| 1825 | 1827 | ||
| 1826 | Load = AddHdr(PT_LOAD, NewFlags); | 1828 | Load = AddHdr(PT_LOAD, NewFlags); |
deps/lld/docs/ReleaseNotes.rst+7-1| ... | @@ -29,7 +29,13 @@ ELF Improvements | ... | @@ -29,7 +29,13 @@ ELF Improvements |
| 29 | COFF Improvements | 29 | COFF Improvements |
| 30 | ----------------- | 30 | ----------------- |
| 31 | 31 | ||
| 32 | * Item 1. | 32 | * Improved correctness of exporting mangled stdcall symbols. |
| 33 | |||
| 34 | * Completed support for ARM64 relocations. | ||
| 35 | |||
| 36 | * Added support for outputting PDB debug info for MinGW targets. | ||
| 37 | |||
| 38 | * Improved compatibility of output binaries with GNU binutils objcopy/strip. | ||
| 33 | 39 | ||
| 34 | MachO Improvements | 40 | MachO Improvements |
| 35 | ------------------ | 41 | ------------------ |
deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp+1| ... | @@ -621,6 +621,7 @@ void ArchHandler_x86_64::applyFixupFinal( | ... | @@ -621,6 +621,7 @@ void ArchHandler_x86_64::applyFixupFinal( |
| 621 | // Fall into llvm_unreachable(). | 621 | // Fall into llvm_unreachable(). |
| 622 | break; | 622 | break; |
| 623 | } | 623 | } |
| 624 | llvm_unreachable("invalid x86_64 Reference Kind"); | ||
| 624 | } | 625 | } |
| 625 | 626 | ||
| 626 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, | 627 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, |
deps/lld/test/COFF/Inputs/associative-comdat-mingw-2.s created+34| ... | @@ -0,0 +1,34 @@ | ||
| 1 | .section .xdata$foo,"dr" | ||
| 2 | .linkonce discard | ||
| 3 | .p2align 3 | ||
| 4 | .long 42 | ||
| 5 | |||
| 6 | .section .xdata$bar,"dr" | ||
| 7 | .linkonce discard | ||
| 8 | .p2align 3 | ||
| 9 | .long 43 | ||
| 10 | |||
| 11 | .section .xdata$baz,"dr" | ||
| 12 | .linkonce discard | ||
| 13 | .p2align 3 | ||
| 14 | .long 44 | ||
| 15 | |||
| 16 | .def foo; | ||
| 17 | .scl 2; | ||
| 18 | .type 32; | ||
| 19 | .endef | ||
| 20 | .section .text$foo,"xr",discard,foo | ||
| 21 | .globl foo | ||
| 22 | .p2align 4 | ||
| 23 | foo: | ||
| 24 | ret | ||
| 25 | |||
| 26 | .def bar; | ||
| 27 | .scl 2; | ||
| 28 | .type 32; | ||
| 29 | .endef | ||
| 30 | .section .text$bar,"xr",discard,bar | ||
| 31 | .globl bar | ||
| 32 | .p2align 4 | ||
| 33 | bar: | ||
| 34 | ret | ||
deps/lld/test/COFF/Inputs/common-replacement.s created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | .globl foo | ||
| 2 | .data | ||
| 3 | .p2align 2, 0 | ||
| 4 | foo: | ||
| 5 | .long 42 | ||
deps/lld/test/COFF/associative-comdat-mingw.s created+73| ... | @@ -0,0 +1,73 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t1.obj | ||
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/associative-comdat-mingw-2.s -filetype=obj -o %t2.obj | ||
| 5 | |||
| 6 | # RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.gc.exe -verbose | ||
| 7 | # RUN: llvm-readobj -sections %t.gc.exe | FileCheck %s | ||
| 8 | |||
| 9 | # CHECK: Sections [ | ||
| 10 | # CHECK: Section { | ||
| 11 | # CHECK: Number: 2 | ||
| 12 | # CHECK-LABEL: Name: .rdata (2E 72 64 61 74 61 00 00) | ||
| 13 | # This is the critical check to show that only *one* definition of | ||
| 14 | # .xdata$foo was retained. This *must* be 4. | ||
| 15 | # Make sure that no other .xdata sections get included, which would | ||
| 16 | # increase the size here. | ||
| 17 | # CHECK-NEXT: VirtualSize: 0x4 | ||
| 18 | |||
| 19 | .text | ||
| 20 | .def main; | ||
| 21 | .scl 2; | ||
| 22 | .type 32; | ||
| 23 | .endef | ||
| 24 | .globl main | ||
| 25 | .p2align 4, 0x90 | ||
| 26 | main: | ||
| 27 | call foo | ||
| 28 | retq | ||
| 29 | |||
| 30 | # Defines .text$foo (which has a leader symbol and is referenced like | ||
| 31 | # normally), and .xdata$foo (which lacks a leader symbol, which normally | ||
| 32 | # would be declared associative to the symbol foo). | ||
| 33 | # .xdata$foo should be implicitly treated as associative to foo and brought | ||
| 34 | # in, while .xdata$bar, implicitly associative to bar, not included, and | ||
| 35 | # .xdata$baz not included since there's no symbol baz. | ||
| 36 | |||
| 37 | # GNU binutils ld doesn't do this at all, but always includes all .xdata/.pdata | ||
| 38 | # comdat sections, even if --gc-sections is used. | ||
| 39 | |||
| 40 | .section .xdata$foo,"dr" | ||
| 41 | .linkonce discard | ||
| 42 | .p2align 3 | ||
| 43 | .long 42 | ||
| 44 | |||
| 45 | .section .xdata$bar,"dr" | ||
| 46 | .linkonce discard | ||
| 47 | .p2align 3 | ||
| 48 | .long 43 | ||
| 49 | |||
| 50 | .section .xdata$baz,"dr" | ||
| 51 | .linkonce discard | ||
| 52 | .p2align 3 | ||
| 53 | .long 44 | ||
| 54 | |||
| 55 | .def foo; | ||
| 56 | .scl 2; | ||
| 57 | .type 32; | ||
| 58 | .endef | ||
| 59 | .section .text$foo,"xr",discard,foo | ||
| 60 | .globl foo | ||
| 61 | .p2align 4 | ||
| 62 | foo: | ||
| 63 | ret | ||
| 64 | |||
| 65 | .def bar; | ||
| 66 | .scl 2; | ||
| 67 | .type 32; | ||
| 68 | .endef | ||
| 69 | .section .text$bar,"xr",discard,bar | ||
| 70 | .globl bar | ||
| 71 | .p2align 4 | ||
| 72 | bar: | ||
| 73 | ret | ||
deps/lld/test/COFF/common-replacement.s created+35| ... | @@ -0,0 +1,35 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | |||
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t1.obj | ||
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/common-replacement.s -filetype=obj -o %t2.obj | ||
| 5 | |||
| 6 | # RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.exe -verbose 2>&1 \ | ||
| 7 | # RUN: | FileCheck -check-prefix VERBOSE %s | ||
| 8 | # RUN: llvm-readobj -s %t.exe | FileCheck -check-prefix SECTIONS %s | ||
| 9 | |||
| 10 | # VERBOSE: -aligncomm:"foo",2 | ||
| 11 | |||
| 12 | # As long as the .comm symbol is replaced with actual data, RawDataSize | ||
| 13 | # below should be nonzero. | ||
| 14 | |||
| 15 | # SECTIONS: Name: .data (2E 64 61 74 61 00 00 00) | ||
| 16 | # SECTIONS-NEXT: VirtualSize: 0x8 | ||
| 17 | # SECTIONS-NEXT: VirtualAddress: 0x2000 | ||
| 18 | # SECTIONS-NEXT: RawDataSize: 512 | ||
| 19 | |||
| 20 | |||
| 21 | .text | ||
| 22 | .def main; | ||
| 23 | .scl 2; | ||
| 24 | .type 32; | ||
| 25 | .endef | ||
| 26 | .globl main | ||
| 27 | .p2align 4, 0x90 | ||
| 28 | main: | ||
| 29 | movl foo(%rip), %eax | ||
| 30 | retq | ||
| 31 | |||
| 32 | # This produces an aligncomm directive, but when linking in | ||
| 33 | # Inputs/common-replacement.s, this symbol is replaced by a normal defined | ||
| 34 | # symbol instead. | ||
| 35 | .comm foo, 4, 2 | ||
deps/lld/test/ELF/linkerscript/Inputs/at6.s created+11| ... | @@ -0,0 +1,11 @@ | ||
| 1 | .global _start | ||
| 2 | .text | ||
| 3 | _start: | ||
| 4 | nop | ||
| 5 | |||
| 6 | .section .sec1,"aw",@progbits | ||
| 7 | .long 1 | ||
| 8 | |||
| 9 | .section .sec2,"aw",@progbits | ||
| 10 | .long 2 | ||
| 11 | |||
deps/lld/test/ELF/linkerscript/Inputs/at7.s created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | .global _start | ||
| 2 | .text | ||
| 3 | _start: | ||
| 4 | nop | ||
| 5 | |||
| 6 | .section .sec, "aw" | ||
| 7 | .word 4 | ||
deps/lld/test/ELF/linkerscript/Inputs/at8.s created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | .section .sec1,"aw",@progbits | ||
| 2 | .quad 1 | ||
| 3 | |||
| 4 | .section .sec2,"aw",@progbits | ||
| 5 | .quad 2 | ||
| 6 | |||
| 7 | .section .sec3,"aw",@progbits | ||
| 8 | .quad 3 | ||
deps/lld/test/ELF/linkerscript/at6.test created+30| ... | @@ -0,0 +1,30 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at6.s -o %t.o | ||
| 3 | # RUN: ld.lld %t.o --script %s -o %t | ||
| 4 | # RUN: llvm-readelf -sections -program-headers %t | FileCheck %s | ||
| 5 | |||
| 6 | MEMORY { | ||
| 7 | FLASH : ORIGIN = 0x08000000, LENGTH = 0x100 | ||
| 8 | RAM : ORIGIN = 0x20000000, LENGTH = 0x200 | ||
| 9 | } | ||
| 10 | |||
| 11 | SECTIONS { | ||
| 12 | .text : { *(.text) } > FLASH | ||
| 13 | .sec1 : { *(.sec1) } > RAM | ||
| 14 | .sec2 : { *(.sec2) } > RAM AT > FLASH | ||
| 15 | } | ||
| 16 | |||
| 17 | # Make sure we create a separate PT_LOAD entry for .sec2. Previously, | ||
| 18 | # it was added to the PT_LOAD entry of .sec1 | ||
| 19 | |||
| 20 | # CHECK: Name Type Address Off | ||
| 21 | # CHECK: .text PROGBITS 0000000008000000 001000 | ||
| 22 | # CHECK: .sec1 PROGBITS 0000000020000000 002000 | ||
| 23 | # CHECK: .sec2 PROGBITS 0000000020000004 002004 | ||
| 24 | |||
| 25 | # CHECK: Program Headers: | ||
| 26 | # CHECK: Type Offset VirtAddr PhysAddr | ||
| 27 | # CHECK-NEXT: LOAD 0x001000 0x0000000008000000 0x0000000008000000 | ||
| 28 | # CHECK-NEXT: LOAD 0x002000 0x0000000020000000 0x0000000020000000 | ||
| 29 | # CHECK-NEXT: LOAD 0x002004 0x0000000020000004 0x0000000008000001 | ||
| 30 | # CHECK-NOT: LOAD | ||
deps/lld/test/ELF/linkerscript/at7.test created+28| ... | @@ -0,0 +1,28 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at7.s -o %t.o | ||
| 3 | # RUN: ld.lld %t.o --script %s -o %t | ||
| 4 | # RUN: llvm-readelf -sections -program-headers %t | FileCheck %s | ||
| 5 | |||
| 6 | MEMORY { | ||
| 7 | RAM : ORIGIN = 0x20000000, LENGTH = 0x200 | ||
| 8 | } | ||
| 9 | |||
| 10 | SECTIONS { | ||
| 11 | .text : { *(.text) } > RAM AT> RAM | ||
| 12 | .sec : { *(.sec) } > RAM | ||
| 13 | } | ||
| 14 | |||
| 15 | # Make sure the memory for the .text section is only reserved once. | ||
| 16 | # Previously, the location counter for both MemRegion and LMARegion | ||
| 17 | # was increased unconditionally. | ||
| 18 | |||
| 19 | |||
| 20 | # CHECK: Name Type Address Off | ||
| 21 | # CHECK: .text PROGBITS 0000000020000000 001000 | ||
| 22 | # CHECK: .sec PROGBITS 0000000020000001 001001 | ||
| 23 | |||
| 24 | # CHECK: Program Headers: | ||
| 25 | # CHECK: Type Offset VirtAddr PhysAddr | ||
| 26 | # CHECK-NEXT: LOAD 0x001000 0x0000000020000000 0x0000000020000000 | ||
| 27 | # CHECK-NEXT: LOAD 0x001001 0x0000000020000001 0x0000000020000001 | ||
| 28 | # CHECK-NOT: LOAD | ||
deps/lld/test/ELF/linkerscript/at8.test created+31| ... | @@ -0,0 +1,31 @@ | ||
| 1 | # REQUIRES: x86 | ||
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/at8.s -o %t.o | ||
| 3 | # RUN: ld.lld %t.o --script %s -o %t | ||
| 4 | # RUN: llvm-readelf -sections -program-headers %t | FileCheck %s | ||
| 5 | |||
| 6 | MEMORY { | ||
| 7 | FLASH : ORIGIN = 0x08000000, LENGTH = 0x100 | ||
| 8 | RAM : ORIGIN = 0x20000000, LENGTH = 0x200 | ||
| 9 | } | ||
| 10 | |||
| 11 | SECTIONS { | ||
| 12 | .text : { *(.text) } > FLASH | ||
| 13 | .sec1 : { *(.sec1) } > RAM AT > FLASH | ||
| 14 | .sec2 : { *(.sec2) } > RAM | ||
| 15 | .sec3 : { *(.sec3) } > RAM AT > FLASH | ||
| 16 | } | ||
| 17 | |||
| 18 | # Make sure we do not issue a load-address overlap error | ||
| 19 | # Previously, .sec3 would overwrite the LMAOffset in the | ||
| 20 | # PT_LOAD header. | ||
| 21 | |||
| 22 | # CHECK: Name Type Address Off | ||
| 23 | # CHECK: .text PROGBITS 0000000008000000 001000 | ||
| 24 | # CHECK: .sec1 PROGBITS 0000000020000000 001000 | ||
| 25 | # CHECK: .sec2 PROGBITS 0000000020000008 001008 | ||
| 26 | # CHECK: .sec3 PROGBITS 0000000020000010 001010 | ||
| 27 | |||
| 28 | # CHECK: Program Headers: | ||
| 29 | # CHECK: Type Offset VirtAddr PhysAddr | ||
| 30 | # CHECK-NEXT: LOAD 0x001000 0x0000000020000000 0x0000000008000000 | ||
| 31 | # CHECK-NOT: LOAD | ||
deps/lld/test/ELF/lto/cache.ll+1-1| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | ; RUN: ls %t.cache | count 4 | 13 | ; RUN: ls %t.cache | count 4 |
| 14 | 14 | ||
| 15 | ; Create a file of size 64KB. | 15 | ; Create a file of size 64KB. |
| 16 | ; RUN: "%python" -c "print(' ' * 65536)" > %t.cache/llvmcache-foo | 16 | ; RUN: %python -c "print(' ' * 65536)" > %t.cache/llvmcache-foo |
| 17 | 17 | ||
| 18 | ; This should leave the file in place. | 18 | ; This should leave the file in place. |
| 19 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t3 %t2.o %t.o | 19 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t3 %t2.o %t.o |
deps/lld/test/ELF/x86-64-reloc-error2.s+7-3| ... | @@ -1,14 +1,18 @@ | ... | @@ -1,14 +1,18 @@ |
| 1 | # REQUIRES: x86 | 1 | # REQUIRES: x86 |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | # RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s | 3 | # RUN: not ld.lld --entry=func --gc-sections %t.o -o /dev/null 2>&1 | FileCheck %s |
| 4 | 4 | ||
| 5 | ## Check we are able to find a function symbol that encloses | 5 | ## Check we are able to find a function symbol that encloses |
| 6 | ## a given location when reporting error messages. | 6 | ## a given location when reporting error messages. |
| 7 | # CHECK: {{.*}}.o:(function func): relocation R_X86_64_32S out of range: -281474974609408 is not in [-2147483648, 2147483647] | 7 | # CHECK: {{.*}}.o:(function func): relocation R_X86_64_32S out of range: -281474974609408 is not in [-2147483648, 2147483647] |
| 8 | 8 | ||
| 9 | # This mergeable section will be garbage collected. We had a crash issue in that case. Test it. | ||
| 10 | .section .rodata.str1,"aMS",@progbits,1 | ||
| 11 | .asciz "a" | ||
| 12 | |||
| 9 | .section .text.func, "ax", %progbits | 13 | .section .text.func, "ax", %progbits |
| 10 | .globl func | 14 | .globl func |
| 11 | .type func,@function | 15 | .type func,@function |
| 12 | .size func, 0x10 | ||
| 13 | func: | 16 | func: |
| 14 | movq func - 0x1000000000000, %rdx | 17 | movq $func - 0x1000000000000, %rdx |
| 18 | .size func, .-func |
deps/lld/test/mach-o/dependency_info.yaml+1-1| ... | @@ -9,7 +9,7 @@ | ... | @@ -9,7 +9,7 @@ |
| 9 | # RUN: -F/Custom/Frameworks \ | 9 | # RUN: -F/Custom/Frameworks \ |
| 10 | # RUN: -framework Bar \ | 10 | # RUN: -framework Bar \ |
| 11 | # RUN: -framework Foo | 11 | # RUN: -framework Foo |
| 12 | # RUN: '%python' %p/Inputs/DependencyDump.py %t.info | FileCheck %s | 12 | # RUN: %python %p/Inputs/DependencyDump.py %t.info | FileCheck %s |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | # CHECK: linker-vers: lld | 15 | # CHECK: linker-vers: lld |
deps/lld/test/wasm/lto/cache.ll+1-1| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | ; RUN: ls %t.cache | count 4 | 11 | ; RUN: ls %t.cache | count 4 |
| 12 | 12 | ||
| 13 | ; Create a file of size 64KB. | 13 | ; Create a file of size 64KB. |
| 14 | ; RUN: "%python" -c "print(' ' * 65536)" > %t.cache/llvmcache-foo | 14 | ; RUN: %python -c "print(' ' * 65536)" > %t.cache/llvmcache-foo |
| 15 | 15 | ||
| 16 | ; This should leave the file in place. | 16 | ; This should leave the file in place. |
| 17 | ; RUN: wasm-ld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t.wasm %t2.o %t.o | 17 | ; RUN: wasm-ld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t.wasm %t2.o %t.o |