[lld] r339058 - [COFF] Treat .xdata/.pdata$<sym> as implicitly associative to <sym> for MinGW

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 7 00:46:55 PDT 2018


Merged to 7.0 in r339108.

On Mon, Aug 6, 2018 at 11:26 PM, Martin Storsjo via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: mstorsjo
> Date: Mon Aug  6 14:26:09 2018
> New Revision: 339058
>
> URL: http://llvm.org/viewvc/llvm-project?rev=339058&view=rev
> Log:
> [COFF] Treat .xdata/.pdata$<sym> as implicitly associative to <sym> for MinGW
>
> MinGW configurations don't use associative comdats, as GNU ld doesn't
> support that. Instead they produce normal comdats named .text$sym,
> .xdata$sym and .pdata$sym.
>
> GNU ld doesn't discard any comdats starting with .xdata or .pdata,
> even if --gc-sections is used (while it does discard other unreferenced
> comdats), regardless of what symbol name is used after the $ separator.
>
> For LLD, treat any such comdat as implicitly associative to the base
> symbol. This requires maintaining a map from symbol name to section
> number, but that is only maintained when the MinGW flag has been
> enabled.
>
> Differential Revision: https://reviews.llvm.org/D49700
>
> Added:
>     lld/trunk/test/COFF/Inputs/associative-comdat-mingw-2.s
>     lld/trunk/test/COFF/associative-comdat-mingw.s
> Modified:
>     lld/trunk/COFF/InputFiles.cpp
>     lld/trunk/COFF/InputFiles.h
>
> Modified: lld/trunk/COFF/InputFiles.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=339058&r1=339057&r2=339058&view=diff
> ==============================================================================
> --- lld/trunk/COFF/InputFiles.cpp (original)
> +++ lld/trunk/COFF/InputFiles.cpp Mon Aug  6 14:26:09 2018
> @@ -205,7 +205,13 @@ SectionChunk *ObjFile::readSection(uint3
>
>  void ObjFile::readAssociativeDefinition(
>      COFFSymbolRef Sym, const coff_aux_section_definition *Def) {
> -  SectionChunk *Parent = SparseChunks[Def->getNumber(Sym.isBigObj())];
> +  readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj()));
> +}
> +
> +void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym,
> +                                        const coff_aux_section_definition *Def,
> +                                        uint32_t ParentSection) {
> +  SectionChunk *Parent = SparseChunks[ParentSection];
>
>    // If the parent is pending, it probably means that its section definition
>    // appears after us in the symbol table. Leave the associated section as
> @@ -225,6 +231,35 @@ void ObjFile::readAssociativeDefinition(
>    }
>  }
>
> +void ObjFile::recordPrevailingSymbolForMingw(
> +    COFFSymbolRef Sym, DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {
> +  // For comdat symbols in executable sections, where this is the copy
> +  // of the section chunk we actually include instead of discarding it,
> +  // add the symbol to a map to allow using it for implicitly
> +  // associating .[px]data$<func> sections to it.
> +  int32_t SectionNumber = Sym.getSectionNumber();
> +  SectionChunk *SC = SparseChunks[SectionNumber];
> +  if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) {
> +    StringRef Name;
> +    COFFObj->getSymbolName(Sym, Name);
> +    PrevailingSectionMap[Name] = SectionNumber;
> +  }
> +}
> +
> +void ObjFile::maybeAssociateSEHForMingw(
> +    COFFSymbolRef Sym, const coff_aux_section_definition *Def,
> +    const DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {
> +  StringRef Name;
> +  COFFObj->getSymbolName(Sym, Name);
> +  if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$")) {
> +    // For MinGW, treat .[px]data$<func> as implicitly associative to
> +    // the symbol <func>.
> +    auto ParentSym = PrevailingSectionMap.find(Name);
> +    if (ParentSym != PrevailingSectionMap.end())
> +      readAssociativeDefinition(Sym, Def, ParentSym->second);
> +  }
> +}
> +
>  Symbol *ObjFile::createRegular(COFFSymbolRef Sym) {
>    SectionChunk *SC = SparseChunks[Sym.getSectionNumber()];
>    if (Sym.isExternal()) {
> @@ -248,19 +283,24 @@ void ObjFile::initializeSymbols() {
>    std::vector<uint32_t> PendingIndexes;
>    PendingIndexes.reserve(NumSymbols);
>
> +  DenseMap<StringRef, uint32_t> PrevailingSectionMap;
>    std::vector<const coff_aux_section_definition *> ComdatDefs(
>        COFFObj->getNumberOfSections() + 1);
>
>    for (uint32_t I = 0; I < NumSymbols; ++I) {
>      COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I));
> +    bool PrevailingComdat;
>      if (COFFSym.isUndefined()) {
>        Symbols[I] = createUndefined(COFFSym);
>      } else if (COFFSym.isWeakExternal()) {
>        Symbols[I] = createUndefined(COFFSym);
>        uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex;
>        WeakAliases.emplace_back(Symbols[I], TagIndex);
> -    } else if (Optional<Symbol *> OptSym = createDefined(COFFSym, ComdatDefs)) {
> +    } else if (Optional<Symbol *> OptSym =
> +                   createDefined(COFFSym, ComdatDefs, PrevailingComdat)) {
>        Symbols[I] = *OptSym;
> +      if (Config->MinGW && PrevailingComdat)
> +        recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap);
>      } else {
>        // createDefined() returns None if a symbol belongs to a section that
>        // was pending at the point when the symbol was read. This can happen in
> @@ -278,9 +318,12 @@ void ObjFile::initializeSymbols() {
>
>    for (uint32_t I : PendingIndexes) {
>      COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
> -    if (auto *Def = Sym.getSectionDefinition())
> +    if (auto *Def = Sym.getSectionDefinition()) {
>        if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
>          readAssociativeDefinition(Sym, Def);
> +      else if (Config->MinGW)
> +        maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap);
> +    }
>      if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) {
>        StringRef Name;
>        COFFObj->getSymbolName(Sym, Name);
> @@ -306,7 +349,9 @@ Symbol *ObjFile::createUndefined(COFFSym
>
>  Optional<Symbol *> ObjFile::createDefined(
>      COFFSymbolRef Sym,
> -    std::vector<const coff_aux_section_definition *> &ComdatDefs) {
> +    std::vector<const coff_aux_section_definition *> &ComdatDefs,
> +    bool &Prevailing) {
> +  Prevailing = false;
>    auto GetName = [&]() {
>      StringRef S;
>      COFFObj->getSymbolName(Sym, S);
> @@ -352,7 +397,6 @@ Optional<Symbol *> ObjFile::createDefine
>    if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) {
>      ComdatDefs[SectionNumber] = nullptr;
>      Symbol *Leader;
> -    bool Prevailing;
>      if (Sym.isExternal()) {
>        std::tie(Leader, Prevailing) =
>            Symtab->addComdat(this, GetName(), Sym.getGeneric());
>
> Modified: lld/trunk/COFF/InputFiles.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=339058&r1=339057&r2=339058&view=diff
> ==============================================================================
> --- lld/trunk/COFF/InputFiles.h (original)
> +++ lld/trunk/COFF/InputFiles.h Mon Aug  6 14:26:09 2018
> @@ -13,6 +13,7 @@
>  #include "Config.h"
>  #include "lld/Common/LLVM.h"
>  #include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/DenseMap.h"
>  #include "llvm/ADT/DenseSet.h"
>  #include "llvm/LTO/LTO.h"
>  #include "llvm/Object/Archive.h"
> @@ -157,10 +158,24 @@ private:
>        COFFSymbolRef COFFSym,
>        const llvm::object::coff_aux_section_definition *Def);
>
> +  void readAssociativeDefinition(
> +      COFFSymbolRef COFFSym,
> +      const llvm::object::coff_aux_section_definition *Def,
> +      uint32_t ParentSection);
> +
> +  void recordPrevailingSymbolForMingw(
> +      COFFSymbolRef COFFSym,
> +      llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);
> +
> +  void maybeAssociateSEHForMingw(
> +      COFFSymbolRef Sym, const llvm::object::coff_aux_section_definition *Def,
> +      const llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);
> +
>    llvm::Optional<Symbol *>
>    createDefined(COFFSymbolRef Sym,
>                  std::vector<const llvm::object::coff_aux_section_definition *>
> -                    &ComdatDefs);
> +                    &ComdatDefs,
> +                bool &PrevailingComdat);
>    Symbol *createRegular(COFFSymbolRef Sym);
>    Symbol *createUndefined(COFFSymbolRef Sym);
>
>
> Added: lld/trunk/test/COFF/Inputs/associative-comdat-mingw-2.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/associative-comdat-mingw-2.s?rev=339058&view=auto
> ==============================================================================
> --- lld/trunk/test/COFF/Inputs/associative-comdat-mingw-2.s (added)
> +++ lld/trunk/test/COFF/Inputs/associative-comdat-mingw-2.s Mon Aug  6 14:26:09 2018
> @@ -0,0 +1,34 @@
> +        .section        .xdata$foo,"dr"
> +        .linkonce       discard
> +        .p2align        3
> +        .long           42
> +
> +        .section        .xdata$bar,"dr"
> +        .linkonce       discard
> +        .p2align        3
> +        .long           43
> +
> +        .section        .xdata$baz,"dr"
> +        .linkonce       discard
> +        .p2align        3
> +        .long           44
> +
> +        .def            foo;
> +        .scl            2;
> +        .type           32;
> +        .endef
> +        .section        .text$foo,"xr",discard,foo
> +        .globl          foo
> +        .p2align        4
> +foo:
> +        ret
> +
> +        .def            bar;
> +        .scl            2;
> +        .type           32;
> +        .endef
> +        .section        .text$bar,"xr",discard,bar
> +        .globl          bar
> +        .p2align        4
> +bar:
> +        ret
>
> Added: lld/trunk/test/COFF/associative-comdat-mingw.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/associative-comdat-mingw.s?rev=339058&view=auto
> ==============================================================================
> --- lld/trunk/test/COFF/associative-comdat-mingw.s (added)
> +++ lld/trunk/test/COFF/associative-comdat-mingw.s Mon Aug  6 14:26:09 2018
> @@ -0,0 +1,73 @@
> +# REQUIRES: x86
> +
> +# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t1.obj
> +# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/associative-comdat-mingw-2.s -filetype=obj -o %t2.obj
> +
> +# RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.gc.exe -verbose
> +# RUN: llvm-readobj -sections %t.gc.exe | FileCheck %s
> +
> +# CHECK: Sections [
> +# CHECK:   Section {
> +# 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.
> +#             Make sure that no other .xdata sections get included, which would
> +#             increase the size here.
> +# CHECK-NEXT:     VirtualSize: 0x4
> +
> +        .text
> +        .def            main;
> +        .scl            2;
> +        .type           32;
> +        .endef
> +        .globl          main
> +        .p2align        4, 0x90
> +main:
> +        call            foo
> +        retq
> +
> +# Defines .text$foo (which has a leader symbol and is referenced like
> +# normally), and .xdata$foo (which lacks a leader symbol, which normally
> +# would be declared associative to the symbol foo).
> +# .xdata$foo should be implicitly treated as associative to foo and brought
> +# in, while .xdata$bar, implicitly associative to bar, not included, and
> +# .xdata$baz not included since there's no symbol baz.
> +
> +# GNU binutils ld doesn't do this at all, but always includes all .xdata/.pdata
> +# comdat sections, even if --gc-sections is used.
> +
> +        .section        .xdata$foo,"dr"
> +        .linkonce       discard
> +        .p2align        3
> +        .long           42
> +
> +        .section        .xdata$bar,"dr"
> +        .linkonce       discard
> +        .p2align        3
> +        .long           43
> +
> +        .section        .xdata$baz,"dr"
> +        .linkonce       discard
> +        .p2align        3
> +        .long           44
> +
> +        .def            foo;
> +        .scl            2;
> +        .type           32;
> +        .endef
> +        .section        .text$foo,"xr",discard,foo
> +        .globl          foo
> +        .p2align        4
> +foo:
> +        ret
> +
> +        .def            bar;
> +        .scl            2;
> +        .type           32;
> +        .endef
> +        .section        .text$bar,"xr",discard,bar
> +        .globl          bar
> +        .p2align        4
> +bar:
> +        ret
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list