diff options
| -rw-r--r-- | lld/ELF/InputSection.cpp | 50 | ||||
| -rw-r--r-- | lld/ELF/InputSection.h | 31 | ||||
| -rw-r--r-- | lld/ELF/MarkLive.cpp | 5 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 43 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 3 |
5 files changed, 56 insertions, 76 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 835e8c51200..58e8e63bf6d 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -414,13 +414,12 @@ typename ELFT::uint EHInputSection<ELFT>::getOffset(uintX_t Offset) { // identify the start of the output .eh_frame. Handle this special case. if (this->getSectionHdr()->sh_size == 0) return Offset; - std::pair<uintX_t, uintX_t> *I = this->getRangeAndSize(Offset).first; - uintX_t Base = I->second; - if (Base == uintX_t(-1)) + SectionPiece *Piece = this->getRangeAndSize(Offset).first; + if (Piece->OutputOff == size_t(-1)) return -1; // Not in the output - uintX_t Addend = Offset - I->first; - return Base + Addend; + uintX_t Addend = Offset - Piece->InputOff; + return Piece->OutputOff + Addend; } static size_t findNull(StringRef S, size_t EntSize) { @@ -443,17 +442,14 @@ MergeInputSection<ELFT>::MergeInputSection(elf::ObjectFile<ELFT> *F, uintX_t EntSize = Header->sh_entsize; ArrayRef<uint8_t> D = this->getSectionData(); StringRef Data((const char *)D.data(), D.size()); - std::vector<std::pair<uintX_t, uintX_t>> &Offsets = this->Offsets; - uintX_t V = Config->GcSections ? MergeInputSection<ELFT>::PieceDead - : MergeInputSection<ELFT>::PieceLive; if (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"); - Offsets.push_back(std::make_pair(Offset, V)); + this->Pieces.emplace_back(Offset); uintX_t Size = End + EntSize; Data = Data.substr(Size); Offset += Size; @@ -465,7 +461,7 @@ MergeInputSection<ELFT>::MergeInputSection(elf::ObjectFile<ELFT> *F, size_t Size = Data.size(); assert((Size % EntSize) == 0); for (unsigned I = 0, N = Size; I != N; I += EntSize) - Offsets.push_back(std::make_pair(I, V)); + this->Pieces.emplace_back(I); } template <class ELFT> @@ -474,8 +470,7 @@ bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) { } template <class ELFT> -std::pair<std::pair<typename ELFT::uint, typename ELFT::uint> *, - typename ELFT::uint> +std::pair<SectionPiece *, typename ELFT::uint> SplitInputSection<ELFT>::getRangeAndSize(uintX_t Offset) { ArrayRef<uint8_t> D = this->getSectionData(); StringRef Data((const char *)D.data(), D.size()); @@ -485,37 +480,32 @@ SplitInputSection<ELFT>::getRangeAndSize(uintX_t Offset) { // Find the element this offset points to. auto I = std::upper_bound( - Offsets.begin(), Offsets.end(), Offset, - [](const uintX_t &A, const std::pair<uintX_t, uintX_t> &B) { - return A < B.first; - }); - uintX_t End = I == Offsets.end() ? Data.size() : I->first; + Pieces.begin(), Pieces.end(), Offset, + [](const uintX_t &A, const SectionPiece &B) { return A < B.InputOff; }); + uintX_t End = (I == Pieces.end()) ? Data.size() : I->InputOff; --I; - return std::make_pair(&*I, End); + return {&*I, End}; } template <class ELFT> typename ELFT::uint MergeInputSection<ELFT>::getOffset(uintX_t Offset) { - std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> T = - this->getRangeAndSize(Offset); - std::pair<uintX_t, uintX_t> *I = T.first; + std::pair<SectionPiece *, uintX_t> T = this->getRangeAndSize(Offset); + SectionPiece &Piece = *T.first; uintX_t End = T.second; - uintX_t Start = I->first; + assert(Piece.Live); // Compute the Addend and if the Base is cached, return. - uintX_t Addend = Offset - Start; - uintX_t &Base = I->second; - assert(Base != MergeInputSection<ELFT>::PieceDead); - if (Base != MergeInputSection<ELFT>::PieceLive) - return Base + Addend; + uintX_t Addend = Offset - Piece.InputOff; + if (Piece.OutputOff != size_t(-1)) + return Piece.OutputOff + Addend; // Map the base to the offset in the output section and cache it. ArrayRef<uint8_t> D = this->getSectionData(); StringRef Data((const char *)D.data(), D.size()); - StringRef Entry = Data.substr(Start, End - Start); + StringRef Entry = Data.substr(Piece.InputOff, End - Piece.InputOff); auto *MOS = static_cast<MergeOutputSection<ELFT> *>(this->OutSec); - Base = MOS->getOffset(Entry); - return Base + Addend; + Piece.OutputOff = MOS->getOffset(Entry); + return Piece.OutputOff + Addend; } template <class ELFT> diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 84a48dcfbcd..f2458592b69 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -130,6 +130,14 @@ public: template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded; +// SectionPiece represents a piece of splittable section contents. +struct SectionPiece { + SectionPiece(size_t I) : InputOff(I), Live(!Config->GcSections) {} + size_t InputOff; + size_t OutputOff = -1; + bool Live; +}; + // Usually sections are copied to the output as atomic chunks of data, // but some special types of sections are split into small pieces of data // and each piece is copied to a different place in the output. @@ -142,24 +150,11 @@ public: SplitInputSection(ObjectFile<ELFT> *File, const Elf_Shdr *Header, typename InputSectionBase<ELFT>::Kind SectionKind); - // For each piece of data, we maintain the offsets in the input section and - // in the output section. - std::vector<std::pair<uintX_t, uintX_t>> Offsets; - - // Merge input sections may use the following special values as the output - // section offset: - enum { - // The piece is dead. - PieceDead = uintX_t(-1), - // The piece is live, but an offset has not yet been assigned. After offsets - // have been assigned, if the output section uses tail merging, the field - // will still have this value and the output section offset is computed - // lazilly. - PieceLive = uintX_t(-2), - }; - - std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> - getRangeAndSize(uintX_t Offset); + // Splittable sections are handled as a sequence of data + // rather than a single large blob of data. + std::vector<SectionPiece> Pieces; + + std::pair<SectionPiece *, uintX_t> getRangeAndSize(uintX_t Offset); }; // This corresponds to a SHF_MERGE section of an input file. diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index dc653d9697a..6680f695041 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -143,9 +143,8 @@ template <class ELFT> void elf::markLive() { if (!R.Sec) return; if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(R.Sec)) { - std::pair<std::pair<uintX_t, uintX_t> *, uintX_t> T = - MS->getRangeAndSize(R.Offset); - T.first->second = MergeInputSection<ELFT>::PieceLive; + std::pair<SectionPiece *, uintX_t> T = MS->getRangeAndSize(R.Offset); + T.first->Live = true; } if (R.Sec->Live) return; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index b16035bfac6..e02411a7e1b 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -978,10 +978,9 @@ EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index) template <class ELFT> StringRef EHRegion<ELFT>::data() const { ArrayRef<uint8_t> SecData = S->getSectionData(); - ArrayRef<std::pair<uintX_t, uintX_t>> Offsets = S->Offsets; - size_t Start = Offsets[Index].first; - size_t End = - Index == Offsets.size() - 1 ? SecData.size() : Offsets[Index + 1].first; + size_t Start = S->Pieces[Index].InputOff; + size_t End = (Index == S->Pieces.size() - 1) ? SecData.size() + : S->Pieces[Index + 1].InputOff; return StringRef((const char *)SecData.data() + Start, End - Start); } @@ -1142,8 +1141,8 @@ void EHOutputSection<ELFT>::addSectionAux(EHInputSection<ELFT> *S, DenseMap<uintX_t, uintX_t> OffsetToIndex; while (!D.empty()) { - unsigned Index = S->Offsets.size(); - S->Offsets.push_back(std::make_pair(Offset, -1)); + unsigned Index = S->Pieces.size(); + S->Pieces.emplace_back(Offset); uintX_t Length = readEntryLength<ELFT>(D); // If CIE/FDE data length is zero then Length is 4, this @@ -1227,11 +1226,11 @@ template <class ELFT> void EHOutputSection<ELFT>::finalize() { size_t Offset = 0; for (const Cie<ELFT> &C : Cies) { - C.S->Offsets[C.Index].second = Offset; + C.S->Pieces[C.Index].OutputOff = Offset; Offset += alignTo(C.data().size(), sizeof(uintX_t)); for (const EHRegion<ELFT> &F : C.Fdes) { - F.S->Offsets[F.Index].second = Offset; + F.S->Pieces[F.Index].OutputOff = Offset; Offset += alignTo(F.data().size(), sizeof(uintX_t)); } } @@ -1240,11 +1239,11 @@ template <class ELFT> void EHOutputSection<ELFT>::finalize() { template <class ELFT> void EHOutputSection<ELFT>::writeTo(uint8_t *Buf) { const endianness E = ELFT::TargetEndianness; for (const Cie<ELFT> &C : Cies) { - size_t CieOffset = C.S->Offsets[C.Index].second; + size_t CieOffset = C.S->Pieces[C.Index].OutputOff; writeCieFde<ELFT>(Buf + CieOffset, C.data()); for (const EHRegion<ELFT> &F : C.Fdes) { - size_t Offset = F.S->Offsets[F.Index].second; + size_t Offset = F.S->Pieces[F.Index].OutputOff; writeCieFde<ELFT>(Buf + Offset, F.data()); write32<E>(Buf + Offset + 4, Offset + 4 - CieOffset); // Pointer @@ -1284,32 +1283,30 @@ 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) { - for (unsigned I = 0, N = Offsets.size(); I != N; ++I) { - auto &P = Offsets[I]; - if (P.second == MergeInputSection<ELFT>::PieceDead) + for (unsigned I = 0, N = S->Pieces.size(); I != N; ++I) { + SectionPiece &Piece = S->Pieces[I]; + if (!Piece.Live) continue; - uintX_t Start = P.first; - uintX_t End = (I == N - 1) ? Data.size() : Offsets[I + 1].first; + uintX_t Start = Piece.InputOff; + uintX_t End = (I == N - 1) ? Data.size() : S->Pieces[I + 1].InputOff; StringRef Entry = Data.substr(Start, End - Start); uintX_t OutputOffset = Builder.add(Entry); - if (shouldTailMerge()) - OutputOffset = MergeInputSection<ELFT>::PieceLive; - P.second = OutputOffset; + if (!shouldTailMerge()) + Piece.OutputOff = OutputOffset; } return; } // If this is not of type string, every entry has the same size. - for (auto &P : Offsets) { - if (P.second == (uintX_t)-1) + for (SectionPiece &Piece : S->Pieces) { + if (!Piece.Live) continue; - StringRef Entry = Data.substr(P.first, EntSize); - P.second = Builder.add(Entry); + StringRef Entry = Data.substr(Piece.InputOff, EntSize); + Piece.OutputOff = Builder.add(Entry); } } diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 60181c9628a..0105991f8fe 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -855,8 +855,7 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) { if (!D->Section->Live) return false; if (auto *S = dyn_cast<MergeInputSection<ELFT>>(D->Section)) - if (S->getRangeAndSize(D->Value).first->second == - MergeInputSection<ELFT>::PieceDead) + if (!S->getRangeAndSize(D->Value).first->Live) return false; } return true; |

