[lld] r193017 - [PECOFF] Only COMDAT symbols are allowed to be dead-stripped.

Shankar Easwaran shankare at codeaurora.org
Wed Oct 23 14:49:53 PDT 2013


It would remove only if .init_array is not added to the root set. By 
default the reader should make sure certain sections like 
.ctors/.dtors/.init_array ... gets added to the rootset.

Thanks

Shankar Easwaran

On 10/23/2013 4:45 PM, Rui Ueyama wrote:
> I think GNU ld keeps .init_array sections using KEEP linker script macro
> command. Because LLD currently does not the command, I believe it would
> remove .init_array sections, which is wrong.
>
> https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep
>
> In COFF, looks like there's no generic mechanism to tell the linker which
> sections are safe to be GC'ed, and the linker is allowed to remove only
> COMDAT symbols. That's different from ELF.
>
>
> On Wed, Oct 23, 2013 at 2:14 PM, Reid Kleckner <rnk at google.com> wrote:
>
>> ELF uses exactly the same technique for .init_array, and you can use
>> .init_array.priority to get adjust the order of your initializers.  Are you
>> handling it the same way that ELF does, or is this something else?
>>
>> I think link.exe will only dead strip if you use /Gy, which has the effect
>> of putting all functions in COMDATs.  It looks like it will not dead strip
>> data like these function pointers.
>>
>>
>> On Fri, Oct 18, 2013 at 4:54 PM, Rui Ueyama <ruiu at google.com> wrote:
>>
>>> Author: ruiu
>>> Date: Fri Oct 18 18:54:55 2013
>>> New Revision: 193017
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=193017&view=rev
>>> Log:
>>> [PECOFF] Only COMDAT symbols are allowed to be dead-stripped.
>>>
>>> We should dead-strip atoms only if they are created for COMDAT symbols.
>>> If we
>>> remove non-COMDAT atoms from a binary, it will no longer be guaranteed
>>> that
>>> the binary will work correctly.
>>>
>>> In COFF, you can manipulate the order of section contents in the resulting
>>> binary by section name. For example, if you have four sections
>>> .data$unique_prefix_{a,b,c,d}, it's guaranteed that the contents of A, B,
>>> C,
>>> and D will be consecutive in the resulting .data section in that order.
>>> Thus, you can access B's and C's contents by incrementing a pointer
>>> pointing
>>> to A until it reached to D. That's why we cannot dead-strip B or C even if
>>> no one is directly referencing to them.
>>>
>>> Some object files in the standard library actually use that technique.
>>>
>>> Modified:
>>>      lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h
>>>      lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
>>>      lld/trunk/test/pecoff/grouped-sections.test
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h?rev=193017&r1=193016&r2=193017&view=diff
>>>
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h (original)
>>> +++ lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h Fri Oct 18 18:54:55 2013
>>> @@ -181,17 +181,24 @@ private:
>>>   class COFFDefinedAtom : public COFFDefinedFileAtom {
>>>   public:
>>>     COFFDefinedAtom(const File &file, StringRef name, StringRef
>>> sectionName,
>>> -                  Scope scope, ContentType type, ContentPermissions
>>> perms,
>>> -                  Merge merge, ArrayRef<uint8_t> data, uint64_t ordinal)
>>> +                  Scope scope, ContentType type, bool isComdat,
>>> +                  ContentPermissions perms, Merge merge,
>>> ArrayRef<uint8_t> data,
>>> +                  uint64_t ordinal)
>>>         : COFFDefinedFileAtom(file, name, sectionName, scope, type, perms,
>>>                               ordinal),
>>> -        _merge(merge), _dataref(data) {}
>>> +        _isComdat(isComdat), _merge(merge), _dataref(data) {}
>>>
>>>     virtual Merge merge() const { return _merge; }
>>>     virtual uint64_t size() const { return _dataref.size(); }
>>>     virtual ArrayRef<uint8_t> rawContent() const { return _dataref; }
>>>
>>> +  virtual DeadStripKind deadStrip() const {
>>> +    // Only COMDAT symbols would be dead-stripped.
>>> +    return _isComdat ? deadStripNormal : deadStripNever;
>>> +  }
>>> +
>>>   private:
>>> +  bool _isComdat;
>>>     Merge _merge;
>>>     ArrayRef<uint8_t> _dataref;
>>>   };
>>>
>>> Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=193017&r1=193016&r2=193017&view=diff
>>>
>>> ==============================================================================
>>> --- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)
>>> +++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Fri Oct 18 18:54:55
>>> 2013
>>> @@ -397,6 +397,8 @@ private:
>>>         if (!(sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT))
>>>           continue;
>>>
>>> +      _comdatSections.insert(sec);
>>> +
>>>         if (sym->NumberOfAuxSymbols == 0)
>>>           return llvm::object::object_error::parse_failed;
>>>         const coff_aux_section_definition *aux =
>>> @@ -473,13 +475,14 @@ private:
>>>
>>>       DefinedAtom::ContentType type = getContentType(section);
>>>       DefinedAtom::ContentPermissions perms = getPermissions(section);
>>> +    bool isComdat = (_comdatSections.count(section) == 1);
>>>
>>>       // Create an atom for the entire section.
>>>       if (symbols.empty()) {
>>>         ArrayRef<uint8_t> data(secData.data(), secData.size());
>>>         auto *atom = new (_alloc)
>>>             COFFDefinedAtom(*this, "", sectionName,
>>> Atom::scopeTranslationUnit,
>>> -                          type, perms, _merge[section], data, 0);
>>> +                          type, isComdat, perms, _merge[section], data,
>>> 0);
>>>         atoms.push_back(atom);
>>>         _definedAtomLocations[section][0].push_back(atom);
>>>         return error_code::success();
>>> @@ -490,9 +493,9 @@ private:
>>>       if (symbols[0]->Value != 0) {
>>>         uint64_t size = symbols[0]->Value;
>>>         ArrayRef<uint8_t> data(secData.data(), size);
>>> -      auto *atom = new (_alloc)
>>> -          COFFDefinedAtom(*this, "", sectionName,
>>> Atom::scopeTranslationUnit,
>>> -                          type, perms, _merge[section], data, ++ordinal);
>>> +      auto *atom = new (_alloc) COFFDefinedAtom(
>>> +          *this, "", sectionName, Atom::scopeTranslationUnit, type,
>>> isComdat,
>>> +          perms, _merge[section], data, ++ordinal);
>>>         atoms.push_back(atom);
>>>         _definedAtomLocations[section][0].push_back(atom);
>>>       }
>>> @@ -503,9 +506,9 @@ private:
>>>         const uint8_t *end = (si + 1 == se) ? secData.data() +
>>> secData.size()
>>>                                             : secData.data() + (*(si +
>>> 1))->Value;
>>>         ArrayRef<uint8_t> data(start, end);
>>> -      auto *atom = new (_alloc)
>>> -          COFFDefinedAtom(*this, _symbolName[*si], sectionName,
>>> getScope(*si),
>>> -                          type, perms, _merge[section], data, ++ordinal);
>>> +      auto *atom = new (_alloc) COFFDefinedAtom(
>>> +          *this, _symbolName[*si], sectionName, getScope(*si), type,
>>> isComdat,
>>> +          perms, _merge[section], data, ++ordinal);
>>>         atoms.push_back(atom);
>>>         _symbolAtom[*si] = atom;
>>>         _definedAtomLocations[section][(*si)->Value].push_back(atom);
>>> @@ -696,6 +699,9 @@ private:
>>>     // A map from section to its atoms.
>>>     std::map<const coff_section *, vector<COFFDefinedFileAtom *> >
>>> _sectionAtoms;
>>>
>>> +  // A set of COMDAT sections.
>>> +  std::set<const coff_section *> _comdatSections;
>>> +
>>>     // A map to get whether the section allows its contents to be merged
>>> or not.
>>>     std::map<const coff_section *, DefinedAtom::Merge> _merge;
>>>
>>>
>>> Modified: lld/trunk/test/pecoff/grouped-sections.test
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/grouped-sections.test?rev=193017&r1=193016&r2=193017&view=diff
>>>
>>> ==============================================================================
>>> --- lld/trunk/test/pecoff/grouped-sections.test (original)
>>> +++ lld/trunk/test/pecoff/grouped-sections.test Fri Oct 18 18:54:55 2013
>>> @@ -1,6 +1,6 @@
>>>   # RUN: yaml2obj %p/Inputs/grouped-sections.obj.yaml > %t.obj
>>>   #
>>> -# RUN: lld -flavor link /out:%t1 /subsystem:console /force /opt:noref \
>>> +# RUN: lld -flavor link /out:%t1 /subsystem:console /force \
>>>   # RUN:   -- %t.obj && llvm-objdump -s %t1 | FileCheck %s
>>>   #
>>>   # The file "grouped-sections.obj" has three data sections in the
>>> following
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131023/00970988/attachment.html>


More information about the llvm-commits mailing list