diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-04-22 22:09:35 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-04-22 22:09:35 +0000 |
commit | 0b9531c8e643d63fad0c2b4f3e6738678c421c59 (patch) | |
tree | d48ef9a6916d9e708c9eeb4f6581507f7bf33dbc /lld/ELF/OutputSections.cpp | |
parent | 0aa9845d1581378768a49ab70cff825f5a535d6a (diff) | |
download | bcm5719-llvm-0b9531c8e643d63fad0c2b4f3e6738678c421c59.tar.gz bcm5719-llvm-0b9531c8e643d63fad0c2b4f3e6738678c421c59.zip |
Bring r267164 back with a fix.
The fix is to handle local symbols referring to SHF_MERGE sections.
Original message:
GC entries of SHF_MERGE sections.
It is a fairly direct extension of the gc algorithm. For merge sections
instead of remembering just a live bit, we remember which offsets
were used.
This reduces the .rodata sections in chromium from 9648861 to 9477472
bytes.
llvm-svn: 267233
Diffstat (limited to 'lld/ELF/OutputSections.cpp')
-rw-r--r-- | lld/ELF/OutputSections.cpp | 44 |
1 files changed, 16 insertions, 28 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 65a59bd025f..efcfcb30b9f 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1132,7 +1132,7 @@ void EHOutputSection<ELFT>::addSectionAux(EHInputSection<ELFT> *S, } else { if (!HasReloc) fatal("FDE doesn't reference another section"); - InputSectionBase<ELFT> *Target = S->getRelocTarget(*RelI); + InputSectionBase<ELFT> *Target = S->getRelocTarget(*RelI).first; if (Target && Target->Live) { uint32_t CieOffset = Offset + 4 - ID; auto I = OffsetToIndex.find(CieOffset); @@ -1227,19 +1227,6 @@ template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) { } } -static size_t findNull(StringRef S, size_t EntSize) { - // Optimize the common case. - if (EntSize == 1) - return S.find(0); - - for (unsigned I = 0, N = S.size(); I != N; I += EntSize) { - const char *B = S.begin() + I; - if (std::all_of(B, B + EntSize, [](char C) { return C == 0; })) - return I; - } - return StringRef::npos; -} - template <class ELFT> void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { auto *S = cast<MergeInputSection<ELFT>>(C); @@ -1250,31 +1237,32 @@ void MergeOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) { StringRef Data((const char *)D.data(), D.size()); uintX_t EntSize = S->getSectionHdr()->sh_entsize; this->Header.sh_entsize = EntSize; + MutableArrayRef<std::pair<uintX_t, uintX_t>> Offsets = S->Offsets; // If this is of type string, the contents are null-terminated strings. if (this->Header.sh_flags & SHF_STRINGS) { - uintX_t Offset = 0; - while (!Data.empty()) { - size_t End = findNull(Data, EntSize); - if (End == StringRef::npos) - fatal("string is not null terminated"); - StringRef Entry = Data.substr(0, End + EntSize); + for (unsigned I = 0, N = Offsets.size(); I != N; ++I) { + auto &P = Offsets[I]; + if (P.second == (uintX_t)-1) + continue; + + uintX_t Start = P.first; + uintX_t End = (I == N - 1) ? Data.size() : Offsets[I + 1].first; + StringRef Entry = Data.substr(Start, End - Start); uintX_t OutputOffset = Builder.add(Entry); if (shouldTailMerge()) OutputOffset = -1; - S->Offsets.push_back(std::make_pair(Offset, OutputOffset)); - uintX_t Size = End + EntSize; - Data = Data.substr(Size); - Offset += Size; + P.second = OutputOffset; } return; } // If this is not of type string, every entry has the same size. - for (unsigned I = 0, N = Data.size(); I != N; I += EntSize) { - StringRef Entry = Data.substr(I, EntSize); - size_t OutputOffset = Builder.add(Entry); - S->Offsets.push_back(std::make_pair(I, OutputOffset)); + for (auto &P : Offsets) { + if (P.second == (uintX_t)-1) + continue; + StringRef Entry = Data.substr(P.first, EntSize); + P.second = Builder.add(Entry); } } |