<div dir="ltr">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.<div><br></div><div>
<a href="https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep">https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep</a><br></div><div><br></div><div>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.</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Oct 23, 2013 at 2:14 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">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?<div>
<br></div><div>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.</div></div><div class="HOEnZb">
<div class="h5"><div class="gmail_extra">
<br><br><div class="gmail_quote">On Fri, Oct 18, 2013 at 4:54 PM, Rui Ueyama <span dir="ltr"><<a href="mailto:ruiu@google.com" target="_blank">ruiu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: ruiu<br>
Date: Fri Oct 18 18:54:55 2013<br>
New Revision: 193017<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=193017&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=193017&view=rev</a><br>
Log:<br>
[PECOFF] Only COMDAT symbols are allowed to be dead-stripped.<br>
<br>
We should dead-strip atoms only if they are created for COMDAT symbols. If we<br>
remove non-COMDAT atoms from a binary, it will no longer be guaranteed that<br>
the binary will work correctly.<br>
<br>
In COFF, you can manipulate the order of section contents in the resulting<br>
binary by section name. For example, if you have four sections<br>
.data$unique_prefix_{a,b,c,d}, it's guaranteed that the contents of A, B, C,<br>
and D will be consecutive in the resulting .data section in that order.<br>
Thus, you can access B's and C's contents by incrementing a pointer pointing<br>
to A until it reached to D. That's why we cannot dead-strip B or C even if<br>
no one is directly referencing to them.<br>
<br>
Some object files in the standard library actually use that technique.<br>
<br>
Modified:<br>
lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h<br>
lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp<br>
lld/trunk/test/pecoff/grouped-sections.test<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h?rev=193017&r1=193016&r2=193017&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h?rev=193017&r1=193016&r2=193017&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h (original)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/Atoms.h Fri Oct 18 18:54:55 2013<br>
@@ -181,17 +181,24 @@ private:<br>
class COFFDefinedAtom : public COFFDefinedFileAtom {<br>
public:<br>
COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName,<br>
- Scope scope, ContentType type, ContentPermissions perms,<br>
- Merge merge, ArrayRef<uint8_t> data, uint64_t ordinal)<br>
+ Scope scope, ContentType type, bool isComdat,<br>
+ ContentPermissions perms, Merge merge, ArrayRef<uint8_t> data,<br>
+ uint64_t ordinal)<br>
: COFFDefinedFileAtom(file, name, sectionName, scope, type, perms,<br>
ordinal),<br>
- _merge(merge), _dataref(data) {}<br>
+ _isComdat(isComdat), _merge(merge), _dataref(data) {}<br>
<br>
virtual Merge merge() const { return _merge; }<br>
virtual uint64_t size() const { return _dataref.size(); }<br>
virtual ArrayRef<uint8_t> rawContent() const { return _dataref; }<br>
<br>
+ virtual DeadStripKind deadStrip() const {<br>
+ // Only COMDAT symbols would be dead-stripped.<br>
+ return _isComdat ? deadStripNormal : deadStripNever;<br>
+ }<br>
+<br>
private:<br>
+ bool _isComdat;<br>
Merge _merge;<br>
ArrayRef<uint8_t> _dataref;<br>
};<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=193017&r1=193016&r2=193017&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp?rev=193017&r1=193016&r2=193017&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp Fri Oct 18 18:54:55 2013<br>
@@ -397,6 +397,8 @@ private:<br>
if (!(sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT))<br>
continue;<br>
<br>
+ _comdatSections.insert(sec);<br>
+<br>
if (sym->NumberOfAuxSymbols == 0)<br>
return llvm::object::object_error::parse_failed;<br>
const coff_aux_section_definition *aux =<br>
@@ -473,13 +475,14 @@ private:<br>
<br>
DefinedAtom::ContentType type = getContentType(section);<br>
DefinedAtom::ContentPermissions perms = getPermissions(section);<br>
+ bool isComdat = (_comdatSections.count(section) == 1);<br>
<br>
// Create an atom for the entire section.<br>
if (symbols.empty()) {<br>
ArrayRef<uint8_t> data(secData.data(), secData.size());<br>
auto *atom = new (_alloc)<br>
COFFDefinedAtom(*this, "", sectionName, Atom::scopeTranslationUnit,<br>
- type, perms, _merge[section], data, 0);<br>
+ type, isComdat, perms, _merge[section], data, 0);<br>
atoms.push_back(atom);<br>
_definedAtomLocations[section][0].push_back(atom);<br>
return error_code::success();<br>
@@ -490,9 +493,9 @@ private:<br>
if (symbols[0]->Value != 0) {<br>
uint64_t size = symbols[0]->Value;<br>
ArrayRef<uint8_t> data(secData.data(), size);<br>
- auto *atom = new (_alloc)<br>
- COFFDefinedAtom(*this, "", sectionName, Atom::scopeTranslationUnit,<br>
- type, perms, _merge[section], data, ++ordinal);<br>
+ auto *atom = new (_alloc) COFFDefinedAtom(<br>
+ *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,<br>
+ perms, _merge[section], data, ++ordinal);<br>
atoms.push_back(atom);<br>
_definedAtomLocations[section][0].push_back(atom);<br>
}<br>
@@ -503,9 +506,9 @@ private:<br>
const uint8_t *end = (si + 1 == se) ? secData.data() + secData.size()<br>
: secData.data() + (*(si + 1))->Value;<br>
ArrayRef<uint8_t> data(start, end);<br>
- auto *atom = new (_alloc)<br>
- COFFDefinedAtom(*this, _symbolName[*si], sectionName, getScope(*si),<br>
- type, perms, _merge[section], data, ++ordinal);<br>
+ auto *atom = new (_alloc) COFFDefinedAtom(<br>
+ *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat,<br>
+ perms, _merge[section], data, ++ordinal);<br>
atoms.push_back(atom);<br>
_symbolAtom[*si] = atom;<br>
_definedAtomLocations[section][(*si)->Value].push_back(atom);<br>
@@ -696,6 +699,9 @@ private:<br>
// A map from section to its atoms.<br>
std::map<const coff_section *, vector<COFFDefinedFileAtom *> > _sectionAtoms;<br>
<br>
+ // A set of COMDAT sections.<br>
+ std::set<const coff_section *> _comdatSections;<br>
+<br>
// A map to get whether the section allows its contents to be merged or not.<br>
std::map<const coff_section *, DefinedAtom::Merge> _merge;<br>
<br>
<br>
Modified: lld/trunk/test/pecoff/grouped-sections.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/grouped-sections.test?rev=193017&r1=193016&r2=193017&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/grouped-sections.test?rev=193017&r1=193016&r2=193017&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/pecoff/grouped-sections.test (original)<br>
+++ lld/trunk/test/pecoff/grouped-sections.test Fri Oct 18 18:54:55 2013<br>
@@ -1,6 +1,6 @@<br>
# RUN: yaml2obj %p/Inputs/grouped-sections.obj.yaml > %t.obj<br>
#<br>
-# RUN: lld -flavor link /out:%t1 /subsystem:console /force /opt:noref \<br>
+# RUN: lld -flavor link /out:%t1 /subsystem:console /force \<br>
# RUN: -- %t.obj && llvm-objdump -s %t1 | FileCheck %s<br>
#<br>
# The file "grouped-sections.obj" has three data sections in the following<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>