Index: lld/trunk/COFF/Chunks.h =================================================================== --- lld/trunk/COFF/Chunks.h +++ lld/trunk/COFF/Chunks.h @@ -458,6 +458,19 @@ int Flags; }; +// MinGW specific. A Chunk that contains one pointer-sized absolute value. +class AbsolutePointerChunk : public Chunk { +public: + AbsolutePointerChunk(uint64_t Value) : Value(Value) { + Alignment = getSize(); + } + size_t getSize() const override; + void writeTo(uint8_t *Buf) const override; + +private: + uint64_t Value; +}; + void applyMOV32T(uint8_t *Off, uint32_t V); void applyBranch24T(uint8_t *Off, int32_t V); Index: lld/trunk/COFF/Chunks.cpp =================================================================== --- lld/trunk/COFF/Chunks.cpp +++ lld/trunk/COFF/Chunks.cpp @@ -784,5 +784,18 @@ Builder.write(Buf + OutputSectionOff); } +// MinGW specific. +size_t AbsolutePointerChunk::getSize() const { + return Config->is64() ? 8 : 4; +} + +void AbsolutePointerChunk::writeTo(uint8_t *Buf) const { + if (Config->is64()) { + write64le(Buf + OutputSectionOff, Value); + } else { + write32le(Buf + OutputSectionOff, Value); + } +} + } // namespace coff } // namespace lld Index: lld/trunk/COFF/Driver.cpp =================================================================== --- lld/trunk/COFF/Driver.cpp +++ lld/trunk/COFF/Driver.cpp @@ -1387,6 +1387,8 @@ if (Config->MinGW) { Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0); Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0); + Symtab->addAbsolute(mangle("__CTOR_LIST__"), 0); + Symtab->addAbsolute(mangle("__DTOR_LIST__"), 0); } // This code may add new undefined symbols to the link, which may enqueue more Index: lld/trunk/COFF/Writer.h =================================================================== --- lld/trunk/COFF/Writer.h +++ lld/trunk/COFF/Writer.h @@ -34,6 +34,7 @@ Header.Characteristics = Chars; } void addChunk(Chunk *C); + void insertChunkAtStart(Chunk *C); void merge(OutputSection *Other); ArrayRef getChunks() { return Chunks; } void addPermissions(uint32_t C); Index: lld/trunk/COFF/Writer.cpp =================================================================== --- lld/trunk/COFF/Writer.cpp +++ lld/trunk/COFF/Writer.cpp @@ -176,6 +176,7 @@ template void writeHeader(); void createSEHTable(); void createRuntimePseudoRelocs(); + void insertCtorDtorSymbols(); void createGuardCFTables(); void markSymbolsForRVATable(ObjFile *File, ArrayRef SymIdxChunks, @@ -227,6 +228,8 @@ OutputSection *DidatSec; OutputSection *RsrcSec; OutputSection *RelocSec; + OutputSection *CtorsSec; + OutputSection *DtorsSec; // The first and last .pdata sections in the output file. // @@ -255,6 +258,11 @@ C->setOutputSection(this); } +void OutputSection::insertChunkAtStart(Chunk *C) { + Chunks.insert(Chunks.begin(), C); + C->setOutputSection(this); +} + void OutputSection::setPermissions(uint32_t C) { Header.Characteristics &= ~PermMask; Header.Characteristics |= C; @@ -447,6 +455,8 @@ DidatSec = CreateSection(".didat", DATA | R); RsrcSec = CreateSection(".rsrc", DATA | R); RelocSec = CreateSection(".reloc", DATA | DISCARDABLE | R); + CtorsSec = CreateSection(".ctors", DATA | R | W); + DtorsSec = CreateSection(".dtors", DATA | R | W); // Then bin chunks by name and output characteristics. std::map, std::vector> Map; @@ -543,8 +553,11 @@ if (Config->GuardCF != GuardCFLevel::Off) createGuardCFTables(); - if (Config->MinGW) + if (Config->MinGW) { createRuntimePseudoRelocs(); + + insertCtorDtorSymbols(); + } } // Create .idata section for the DLL-imported symbol table. @@ -1188,6 +1201,29 @@ replaceSymbol(EndSym, EndSym->getName(), EndOfList); } +// MinGW specific. +// The MinGW .ctors and .dtors lists have sentinels at each end; +// a (uintptr_t)-1 at the start and a (uintptr_t)0 at the end. +// There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__ +// and __DTOR_LIST__ respectively. +void Writer::insertCtorDtorSymbols() { + AbsolutePointerChunk *CtorListHead = make(-1); + AbsolutePointerChunk *CtorListEnd = make(0); + AbsolutePointerChunk *DtorListHead = make(-1); + AbsolutePointerChunk *DtorListEnd = make(0); + CtorsSec->insertChunkAtStart(CtorListHead); + CtorsSec->addChunk(CtorListEnd); + DtorsSec->insertChunkAtStart(DtorListHead); + DtorsSec->addChunk(DtorListEnd); + + Symbol *CtorListSym = Symtab->findUnderscore("__CTOR_LIST__"); + Symbol *DtorListSym = Symtab->findUnderscore("__DTOR_LIST__"); + replaceSymbol(CtorListSym, CtorListSym->getName(), + CtorListHead); + replaceSymbol(DtorListSym, DtorListSym->getName(), + DtorListHead); +} + // Handles /section options to allow users to overwrite // section attributes. void Writer::setSectionPermissions() { Index: lld/trunk/test/COFF/associative-comdat-mingw.s =================================================================== --- lld/trunk/test/COFF/associative-comdat-mingw.s +++ lld/trunk/test/COFF/associative-comdat-mingw.s @@ -11,10 +11,11 @@ # CHECK: Number: 2 # CHECK-LABEL: Name: .rdata (2E 72 64 61 74 61 00 00) # This is the critical check to show that only *one* definition of -# .xdata$foo was retained. This *must* be 4. +# .xdata$foo was retained. This *must* be 0x24 (0x4 for the .xdata +# section and 0x20 for the .ctors/.dtors headers/ends). # Make sure that no other .xdata sections get included, which would # increase the size here. -# CHECK-NEXT: VirtualSize: 0x4 +# CHECK-NEXT: VirtualSize: 0x24 .text .def main; Index: lld/trunk/test/COFF/autoimport-arm-data.s =================================================================== --- lld/trunk/test/COFF/autoimport-arm-data.s +++ lld/trunk/test/COFF/autoimport-arm-data.s @@ -12,22 +12,22 @@ # IMPORTS: Import { # IMPORTS-NEXT: Name: autoimport-arm-data.s.tmp-lib.dll -# IMPORTS-NEXT: ImportLookupTableRVA: 0x2040 -# IMPORTS-NEXT: ImportAddressTableRVA: 0x2048 +# IMPORTS-NEXT: ImportLookupTableRVA: 0x2050 +# IMPORTS-NEXT: ImportAddressTableRVA: 0x2058 # IMPORTS-NEXT: Symbol: variable (0) # IMPORTS-NEXT: } # Runtime pseudo reloc list header consisting of 0x0, 0x0, 0x1. -# First runtime pseudo reloc, with import from 0x2048, +# First runtime pseudo reloc, with import from 0x2058, # applied at 0x3000, with a size of 32 bits. # CONTENTS: Contents of section .rdata: -# CONTENTS: 402000 00000000 00000000 01000000 48200000 +# CONTENTS: 402000 00000000 00000000 01000000 58200000 # CONTENTS: 402010 00300000 20000000 -# ptr: pointing at the IAT RVA at 0x2048 +# ptr: pointing at the IAT RVA at 0x2058 # relocs: pointing at the runtime pseudo reloc list at # 0x2000 - 0x2018. # CONTENTS: Contents of section .data: -# CONTENTS: 403000 48204000 00204000 18204000 +# CONTENTS: 403000 58204000 00204000 18204000 .global main .text Index: lld/trunk/test/COFF/autoimport-arm64-data.s =================================================================== --- lld/trunk/test/COFF/autoimport-arm64-data.s +++ lld/trunk/test/COFF/autoimport-arm64-data.s @@ -12,22 +12,22 @@ # IMPORTS: Import { # IMPORTS-NEXT: Name: autoimport-arm64-data.s.tmp-lib.dll -# IMPORTS-NEXT: ImportLookupTableRVA: 0x2040 -# IMPORTS-NEXT: ImportAddressTableRVA: 0x2050 +# IMPORTS-NEXT: ImportLookupTableRVA: 0x2060 +# IMPORTS-NEXT: ImportAddressTableRVA: 0x2070 # IMPORTS-NEXT: Symbol: variable (0) # IMPORTS-NEXT: } # Runtime pseudo reloc list header consisting of 0x0, 0x0, 0x1. -# First runtime pseudo reloc, with import from 0x2050, +# First runtime pseudo reloc, with import from 0x2070, # applied at 0x3000, with a size of 32 bits. # CONTENTS: Contents of section .rdata: -# CONTENTS: 140002000 00000000 00000000 01000000 50200000 +# CONTENTS: 140002000 00000000 00000000 01000000 70200000 # CONTENTS: 140002010 00300000 40000000 -# ptr: pointing at the IAT RVA at 0x2050 +# ptr: pointing at the IAT RVA at 0x2070 # relocs: pointing at the runtime pseudo reloc list at # 0x2000 - 0x2018. # CONTENTS: Contents of section .data: -# CONTENTS: 140003000 50200040 01000000 00200040 01000000 +# CONTENTS: 140003000 70200040 01000000 00200040 01000000 # CONTENTS: 140003010 18200040 01000000 .global main Index: lld/trunk/test/COFF/autoimport-list-ptrs.s =================================================================== --- lld/trunk/test/COFF/autoimport-list-ptrs.s +++ lld/trunk/test/COFF/autoimport-list-ptrs.s @@ -8,7 +8,7 @@ # Even if we didn't actually write any pseudo relocations, # check that the synthetic pointers still are set to a non-null value # CONTENTS: Contents of section .data: -# CONTENTS: 140002000 00200040 01000000 00200040 01000000 +# CONTENTS: 140003000 00200040 01000000 00200040 01000000 .global main .text Index: lld/trunk/test/COFF/autoimport-refptr.s =================================================================== --- lld/trunk/test/COFF/autoimport-refptr.s +++ lld/trunk/test/COFF/autoimport-refptr.s @@ -13,15 +13,15 @@ # IMPORTS: Import { # IMPORTS-NEXT: Name: autoimport-refptr.s.tmp-lib.dll -# IMPORTS-NEXT: ImportLookupTableRVA: 0x2030 -# IMPORTS-NEXT: ImportAddressTableRVA: 0x2040 +# IMPORTS-NEXT: ImportLookupTableRVA: 0x2050 +# IMPORTS-NEXT: ImportAddressTableRVA: 0x2060 # IMPORTS-NEXT: Symbol: variable (0) # IMPORTS-NEXT: } # DISASM: Disassembly of section .text: # DISASM: .text: -# Relative offset at 0x1002 pointing at the IAT at 0x2040 -# DISASM: 140001000: 48 8b 05 39 10 00 00 movq 4153(%rip), %rax +# Relative offset at 0x1002 pointing at the IAT at 0x2060 +# DISASM: 140001000: 48 8b 05 59 10 00 00 movq 4185(%rip), %rax # DISASM: 140001007: 8b 00 movl (%rax), %eax # Relative offset at 0x100b pointing at the .refptr.localvar stub at # 0x2000 Index: lld/trunk/test/COFF/autoimport-x86.s =================================================================== --- lld/trunk/test/COFF/autoimport-x86.s +++ lld/trunk/test/COFF/autoimport-x86.s @@ -13,31 +13,31 @@ # IMPORTS: Import { # IMPORTS-NEXT: Name: autoimport-x86.s.tmp-lib.dll -# IMPORTS-NEXT: ImportLookupTableRVA: 0x2050 -# IMPORTS-NEXT: ImportAddressTableRVA: 0x2060 +# IMPORTS-NEXT: ImportLookupTableRVA: 0x2070 +# IMPORTS-NEXT: ImportAddressTableRVA: 0x2080 # IMPORTS-NEXT: Symbol: variable (0) # IMPORTS-NEXT: } # DISASM: Disassembly of section .text: # DISASM: .text: -# Relative offset at 0x1002 pointing at the IAT at 0x2060. -# DISASM: 140001000: 8b 05 5a 10 00 00 movl 4186(%rip), %eax +# Relative offset at 0x1002 pointing at the IAT at 0x2080. +# DISASM: 140001000: 8b 05 7a 10 00 00 movl 4218(%rip), %eax # DISASM: 140001006: c3 retq # Runtime pseudo reloc list header consisting of 0x0, 0x0, 0x1. -# First runtime pseudo reloc, with import from 0x2060, +# First runtime pseudo reloc, with import from 0x2080, # applied at 0x1002, with a size of 32 bits. -# Second runtime pseudo reloc, with import from 0x2060, +# Second runtime pseudo reloc, with import from 0x2080, # applied at 0x3000, with a size of 64 bits. # CONTENTS: Contents of section .rdata: -# CONTENTS: 140002000 00000000 00000000 01000000 60200000 -# CONTENTS: 140002010 02100000 20000000 60200000 00300000 +# CONTENTS: 140002000 00000000 00000000 01000000 80200000 +# CONTENTS: 140002010 02100000 20000000 80200000 00300000 # CONTENTS: 140002020 40000000 -# ptr: pointing at the IAT RVA at 0x2060 +# ptr: pointing at the IAT RVA at 0x2080 # relocs: pointing at the runtime pseudo reloc list at # 0x2000 - 0x2024. # CONTENTS: Contents of section .data: -# CONTENTS: 140003000 60200040 01000000 00200040 01000000 +# CONTENTS: 140003000 80200040 01000000 00200040 01000000 # CONTENTS: 140003010 24200040 01000000 .global main Index: lld/trunk/test/COFF/common-replacement.s =================================================================== --- lld/trunk/test/COFF/common-replacement.s +++ lld/trunk/test/COFF/common-replacement.s @@ -14,7 +14,7 @@ # SECTIONS: Name: .data (2E 64 61 74 61 00 00 00) # SECTIONS-NEXT: VirtualSize: 0x8 -# SECTIONS-NEXT: VirtualAddress: 0x2000 +# SECTIONS-NEXT: VirtualAddress: 0x3000 # SECTIONS-NEXT: RawDataSize: 512 Index: lld/trunk/test/COFF/ctors_dtors_priority.s =================================================================== --- lld/trunk/test/COFF/ctors_dtors_priority.s +++ lld/trunk/test/COFF/ctors_dtors_priority.s @@ -7,6 +7,11 @@ main: nop +# Check that these symbols point at the right spots. +.data + .quad __CTOR_LIST__ + .quad __DTOR_LIST__ + .section .ctors.00005, "w" .quad 2 .section .ctors, "w" @@ -29,6 +34,12 @@ # CHECK: Contents of section .rdata: # CHECK-NEXT: 140002000 07000000 00000000 08000000 00000000 -# CHECK-NEXT: 140002010 01000000 00000000 02000000 00000000 -# CHECK-NEXT: 140002020 03000000 00000000 04000000 00000000 -# CHECK-NEXT: 140002030 05000000 00000000 06000000 00000000 +# CHECK-NEXT: 140002010 ffffffff ffffffff 01000000 00000000 +# CHECK-NEXT: 140002020 02000000 00000000 03000000 00000000 +# CHECK-NEXT: 140002030 00000000 00000000 ffffffff ffffffff +# CHECK-NEXT: 140002040 04000000 00000000 05000000 00000000 +# CHECK-NEXT: 140002050 06000000 00000000 00000000 00000000 +# __CTOR_LIST__ pointing at 0x140002010 and +# __DTOR_LIST__ pointing at 0x140002038. +# CHECK-NEXT: Contents of section .data: +# CHECK-NEXT: 140003000 10200040 01000000 38200040 01000000 Index: lld/trunk/test/COFF/debug-reloc.s =================================================================== --- lld/trunk/test/COFF/debug-reloc.s +++ lld/trunk/test/COFF/debug-reloc.s @@ -8,35 +8,35 @@ # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s -check-prefix HEADERS # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck %s -check-prefix DEBUG -# SECTIONS: Number: 2 +# SECTIONS: Number: 3 # SECTIONS-NEXT: Name: .buildid (2E 62 75 69 6C 64 69 64) # SECTIONS-NEXT: VirtualSize: 0x35 -# SECTIONS-NEXT: VirtualAddress: 0x2000 -# SECTIONS: Number: 3 +# SECTIONS-NEXT: VirtualAddress: 0x3000 +# SECTIONS: Number: 4 # SECTIONS-NEXT: Name: .data (2E 64 61 74 61 00 00 00) # SECTIONS-NEXT: VirtualSize: 0x8 -# SECTIONS-NEXT: VirtualAddress: 0x3000 +# SECTIONS-NEXT: VirtualAddress: 0x4000 # RELOCS: BaseReloc [ # RELOCS-NEXT: Entry { # RELOCS-NEXT: Type: DIR64 -# RELOCS-NEXT: Address: 0x3000 +# RELOCS-NEXT: Address: 0x4000 # RELOCS-NEXT: } # RELOCS-NEXT: Entry { # RELOCS-NEXT: Type: ABSOLUTE -# RELOCS-NEXT: Address: 0x3000 +# RELOCS-NEXT: Address: 0x4000 # RELOCS-NEXT: } # RELOCS-NEXT: ] -# HEADERS: DebugRVA: 0x2000 +# HEADERS: DebugRVA: 0x3000 # HEADERS: DebugSize: 0x1C # DEBUG: DebugDirectory [ # DEBUG: DebugEntry { # DEBUG: Type: CodeView (0x2) # DEBUG: SizeOfData: 0x19 -# DEBUG: AddressOfRawData: 0x201C -# DEBUG: PointerToRawData: 0x61C +# DEBUG: AddressOfRawData: 0x301C +# DEBUG: PointerToRawData: 0x81C .text .def mainfunc;