summaryrefslogtreecommitdiffstats
path: root/lld/ELF/OutputSections.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-04-22 22:09:35 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-04-22 22:09:35 +0000
commit0b9531c8e643d63fad0c2b4f3e6738678c421c59 (patch)
treed48ef9a6916d9e708c9eeb4f6581507f7bf33dbc /lld/ELF/OutputSections.cpp
parent0aa9845d1581378768a49ab70cff825f5a535d6a (diff)
downloadbcm5719-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.cpp44
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);
}
}
OpenPOWER on IntegriCloud