summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/InputSection.cpp50
-rw-r--r--lld/ELF/InputSection.h31
-rw-r--r--lld/ELF/MarkLive.cpp5
-rw-r--r--lld/ELF/OutputSections.cpp43
-rw-r--r--lld/ELF/Writer.cpp3
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;
OpenPOWER on IntegriCloud