From: Rui Ueyama Date: Thu, 5 Jun 2014 07:37:20 +0000 (+0000) Subject: [PECOFF] Support COMDAT associative sections. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f3cb9d1d57a763d46d4e7e46e660f06c9fb8ad55;p=platform%2Fupstream%2Fllvm.git [PECOFF] Support COMDAT associative sections. COFF supports a feature similar to ELF's section groups. This patch implements it. In ELF, section groups are identified by their names, and they are treated somewhat differently from regular symbols. In COFF, the feature is realized in a more straightforward way. A section can have an annotation saying "if Nth section is linked, link this section too." Implementing such feature is easy. We can add a reference from a target atom to an original atom, so that if the target is linked, the original atom is also linked. If not linked, both will be dead-stripped. So they are treated as a group. I added a new reference type, kindAssociate. It does nothing except preventing referenced atoms from being dead-stripped. No change to the Resolver is needed. Reviewers: Bigcheese, shankarke, atanasyan Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D3946 llvm-svn: 210240 --- diff --git a/lld/include/lld/Core/Reference.h b/lld/include/lld/Core/Reference.h index c5580ef..ee0d88b 100644 --- a/lld/include/lld/Core/Reference.h +++ b/lld/include/lld/Core/Reference.h @@ -91,6 +91,8 @@ public: kindLayoutBefore = 3, // kindGroupChild is treated as a bidirected edge too. kindGroupChild = 4, + // kindAssociate prevents a referenced atom from being dead-stripped. + kindAssociate = 5, }; // A value to be added to the value of a target diff --git a/lld/lib/ReaderWriter/PECOFF/Atoms.h b/lld/lib/ReaderWriter/PECOFF/Atoms.h index c4ae127..7cd7495 100644 --- a/lld/lib/ReaderWriter/PECOFF/Atoms.h +++ b/lld/lib/ReaderWriter/PECOFF/Atoms.h @@ -167,6 +167,13 @@ public: uint64_t ordinal() const override { return _ordinal; } Alignment alignment() const override { return _alignment; } + void associate(COFFDefinedFileAtom *other) { + auto *r = new COFFReference(other, 0, Reference::kindAssociate, + Reference::KindNamespace::all, + Reference::KindArch::all); + addReference(std::unique_ptr(r)); + } + private: StringRef _sectionName; Scope _scope; diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index 4752097..069c710 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -172,6 +172,9 @@ private: // A map to get whether the section allows its contents to be merged or not. std::map _merge; + // COMDAT associative sections + std::map> _association; + // A sorted map to find an atom from a section and an offset within // the section. std::mapSectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE || sym->SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED) @@ -548,19 +552,22 @@ error_code FileCOFF::cacheSectionAttributes() { const coff_section *sec; if (error_code ec = _obj->getSection(sym->SectionNumber, sec)) return ec; + const coff_aux_section_definition *aux = + reinterpret_cast(i.second); - if (_merge.count(sec)) - continue; - if (!(sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT)) - continue; - - _comdatSections.insert(sec); + if (sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT) { + // Read aux symbol data. + _comdatSections.insert(sec); + _merge[sec] = getMerge(aux); + } - if (sym->NumberOfAuxSymbols == 0) - return llvm::object::object_error::parse_failed; - const coff_aux_section_definition *aux = - reinterpret_cast(i.second); - _merge[sec] = getMerge(aux); + // Handle associative sections. + if (aux->Selection == llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { + const coff_section *parent; + if (error_code ec = _obj->getSection(aux->Number, parent)) + return ec; + _association[parent].insert(sec); + } } // The sections that does not have auxiliary symbol are regular sections, in @@ -694,6 +701,28 @@ error_code FileCOFF::AtomizeDefinedSymbols( definedAtoms.push_back(atom); } } + + // A COMDAT section with SELECT_ASSOCIATIVE attribute refer to other + // section. They need to be linked to a binary or dead stripped as a group. + // Here We add a kindAssociate edge between them, so that if a target section + // is linked, the other is also linked. + // + // In a typical use case, parent is a comdat BSS section, and a child is a + // static initializer for the data. + for (auto i : _association) { + const coff_section *parent = i.first; + const std::set &childSections = i.second; + assert(_sectionAtoms[parent].size() > 0); + + COFFDefinedFileAtom *p = _sectionAtoms[parent][0]; + for (const coff_section *sec : childSections) { + if (_sectionAtoms.count(sec)) { + assert(_sectionAtoms[sec].size() > 0); + p->associate(_sectionAtoms[sec][0]); + } + } + } + return error_code(); } diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp index ce81c69..644acd7 100644 --- a/lld/lib/ReaderWriter/Reader.cpp +++ b/lld/lib/ReaderWriter/Reader.cpp @@ -52,6 +52,7 @@ static const Registry::KindStrings kindStrings[] = { {Reference::kindLayoutAfter, "layout-after"}, {Reference::kindLayoutBefore, "layout-before"}, {Reference::kindGroupChild, "group-child"}, + {Reference::kindAssociate, "associate"}, LLD_KIND_STRING_END}; Registry::Registry() { diff --git a/lld/test/pecoff/Inputs/associative1.obj.yaml b/lld/test/pecoff/Inputs/associative1.obj.yaml new file mode 100644 index 0000000..51a7be0 --- /dev/null +++ b/lld/test/pecoff/Inputs/associative1.obj.yaml @@ -0,0 +1,53 @@ +--- +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [] +sections: + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 4 + SectionData: 00000000 + - Name: '.CRT$XCU' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 77777777 +symbols: + - Name: .data + Value: 0 + SectionNumber: 1 + 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 + Selection: IMAGE_COMDAT_SELECT_ANY + - Name: _var + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: '.CRT$XCU' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 4 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 1 + Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE + - Name: _init + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/pecoff/Inputs/associative3.obj.yaml b/lld/test/pecoff/Inputs/associative3.obj.yaml new file mode 100644 index 0000000..ffea761 --- /dev/null +++ b/lld/test/pecoff/Inputs/associative3.obj.yaml @@ -0,0 +1,33 @@ +--- +header: + Machine: IMAGE_FILE_MACHINE_I386 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: 0000000000000000 + Relocations: + - VirtualAddress: 4 + SymbolName: _var + Type: IMAGE_REL_I386_DIR32 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + - Name: _main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: _var + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/pecoff/associative.test b/lld/test/pecoff/associative.test new file mode 100644 index 0000000..f998bef --- /dev/null +++ b/lld/test/pecoff/associative.test @@ -0,0 +1,10 @@ +# RUN: yaml2obj %p/Inputs/associative1.obj.yaml > %t1.obj +# RUN: yaml2obj %p/Inputs/associative1.obj.yaml > %t2.obj +# RUN: yaml2obj %p/Inputs/associative3.obj.yaml > %t3.obj +# +# RUN: lld -flavor link /machine:x86 /subsystem:console /entry:main \ +# RUN: /out:%t.exe -- %t1.obj %t2.obj %t3.obj +# RUN: obj2yaml %t.exe | FileCheck %s + +CHECK: - Name: .CRT +CHECK: SectionData: '77777777'