<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="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">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>