aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/InputSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r--lld/ELF/InputSection.cpp48
1 files changed, 33 insertions, 15 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 98267d1e..1270f27 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -1358,20 +1358,21 @@ SyntheticSection *EhInputSection::getParent() const {
// .eh_frame is a sequence of CIE or FDE records.
// This function splits an input section into records and returns them.
template <class ELFT> void EhInputSection::split() {
- const RelsOrRelas<ELFT> rels = relsOrRelas<ELFT>(/*supportsCrel=*/false);
- // getReloc expects the relocations to be sorted by r_offset. See the comment
- // in scanRelocs.
- if (rels.areRelocsRel()) {
- SmallVector<typename ELFT::Rel, 0> storage;
- split<ELFT>(sortRels(rels.rels, storage));
- } else {
- SmallVector<typename ELFT::Rela, 0> storage;
- split<ELFT>(sortRels(rels.relas, storage));
- }
-}
+ const RelsOrRelas<ELFT> elfRels = relsOrRelas<ELFT>();
+ if (elfRels.areRelocsCrel())
+ preprocessRelocs<ELFT>(elfRels.crels);
+ else if (elfRels.areRelocsRel())
+ preprocessRelocs<ELFT>(elfRels.rels);
+ else
+ preprocessRelocs<ELFT>(elfRels.relas);
+
+ // The loop below expects the relocations to be sorted by offset.
+ auto cmp = [](const Relocation &a, const Relocation &b) {
+ return a.offset < b.offset;
+ };
+ if (!llvm::is_sorted(rels, cmp))
+ llvm::stable_sort(rels, cmp);
-template <class ELFT, class RelTy>
-void EhInputSection::split(ArrayRef<RelTy> rels) {
ArrayRef<uint8_t> d = content();
const char *msg = nullptr;
unsigned relI = 0;
@@ -1397,10 +1398,10 @@ void EhInputSection::split(ArrayRef<RelTy> rels) {
// Find the first relocation that points to [off,off+size). Relocations
// have been sorted by r_offset.
const uint64_t off = d.data() - content().data();
- while (relI != rels.size() && rels[relI].r_offset < off)
+ while (relI != rels.size() && rels[relI].offset < off)
++relI;
unsigned firstRel = -1;
- if (relI != rels.size() && rels[relI].r_offset < off + size)
+ if (relI != rels.size() && rels[relI].offset < off + size)
firstRel = relI;
(id == 0 ? cies : fdes).emplace_back(off, this, size, firstRel);
d = d.slice(size);
@@ -1410,6 +1411,23 @@ void EhInputSection::split(ArrayRef<RelTy> rels) {
<< getObjMsg(d.data() - content().data());
}
+template <class ELFT, class RelTy>
+void EhInputSection::preprocessRelocs(Relocs<RelTy> elfRels) {
+ Ctx &ctx = file->ctx;
+ rels.reserve(elfRels.size());
+ for (auto rel : elfRels) {
+ uint64_t offset = rel.r_offset;
+ Symbol &sym = file->getSymbol(rel.getSymbol(ctx.arg.isMips64EL));
+ RelType type = rel.getType(ctx.arg.isMips64EL);
+ RelExpr expr = ctx.target->getRelExpr(type, sym, content().data() + offset);
+ int64_t addend =
+ RelTy::HasAddend
+ ? getAddend<ELFT>(rel)
+ : ctx.target->getImplicitAddend(content().data() + offset, type);
+ rels.push_back({expr, type, offset, addend, &sym});
+ }
+}
+
// Return the offset in an output section for a given input offset.
uint64_t EhInputSection::getParentOffset(uint64_t offset) const {
auto it = partition_point(