Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -37,8 +37,9 @@ virtual StringRef getName() const = 0; virtual ArrayRef data() const = 0; virtual StringRef getComdat() const = 0; + virtual uint32_t getInputSectionOffset() const = 0; - void copyRelocations(const WasmSection &Section); + void copyRelocations(ArrayRef Rs) { Relocations = Rs; } uint32_t getSize() const { return data().size(); } void writeTo(uint8_t *SectionStart) const; @@ -59,7 +60,6 @@ InputChunk(const ObjFile *F) : File(F) {} virtual ~InputChunk() = default; void calcRelocations(); - virtual uint32_t getInputSectionOffset() const = 0; std::vector Relocations; int32_t OutputOffset = 0; @@ -82,6 +82,9 @@ StringRef getName() const override { return Segment.Data.Name; } ArrayRef data() const override { return Segment.Data.Content; } StringRef getComdat() const override { return Segment.Data.Comdat; } + uint32_t getInputSectionOffset() const override { + return Segment.SectionOffset; + } // Translate an offset in the input segment to an offset in the output // segment. @@ -101,10 +104,6 @@ int32_t OutputSegmentOffset = 0; protected: - uint32_t getInputSectionOffset() const override { - return Segment.SectionOffset; - } - const WasmSegment &Segment; const OutputSegment *OutputSeg = nullptr; }; @@ -122,6 +121,9 @@ return File->CodeSection->Content.slice(getInputSectionOffset(), Function->Size); } StringRef getComdat() const override { return Function->Comdat; } + uint32_t getInputSectionOffset() const override { + return Function->CodeSectionOffset; + } uint32_t getOutputIndex() const { return OutputIndex.getValue(); } bool hasOutputIndex() const { return OutputIndex.hasValue(); } @@ -130,10 +132,6 @@ const WasmSignature &Signature; protected: - uint32_t getInputSectionOffset() const override { - return Function->CodeSectionOffset; - } - const WasmFunction *Function; llvm::Optional OutputIndex; }; Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -29,16 +29,6 @@ return Address + Delta; } -void InputChunk::copyRelocations(const WasmSection &Section) { - if (Section.Relocations.empty()) - return; - size_t Start = getInputSectionOffset(); - size_t Size = getSize(); - for (const WasmRelocation &R : Section.Relocations) - if (R.Offset >= Start && R.Offset < Start + Size) - Relocations.push_back(R); -} - static void applyRelocation(uint8_t *Buf, const OutputRelocation &Reloc) { DEBUG(dbgs() << "write reloc: type=" << Reloc.Reloc.Type << " index=" << Reloc.Reloc.Index << " value=" << Reloc.Value Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -214,6 +214,48 @@ return !Comdat.empty() && Symtab->findComdat(Comdat) != this; } +static ArrayRef sortRelocations( + ArrayRef Relocations, + std::vector &Vec) { + auto RelocLess = [](const WasmRelocation &R1, const WasmRelocation &R2) { + return R1.Offset < R2.Offset; + }; + if (std::is_sorted(Relocations.begin(), Relocations.end(), RelocLess)) + return Relocations; + Vec.assign(Relocations.begin(), Relocations.end()); + std::sort(Vec.begin(), Vec.end(), RelocLess); + return Vec; +} + +template +static void copyRelocations(const std::vector SortedChunks, + const WasmSection* Section) { + if (!Section || Section->Relocations.empty()) + return; + + std::vector Buf; + auto SortedRelocations = sortRelocations(Section->Relocations, Buf); + assert(std::is_sorted( + SortedChunks.begin(), SortedChunks.end(), + [](InputChunk *C1, InputChunk *C2) { + return C1->getInputSectionOffset() < C2->getInputSectionOffset(); + })); + + auto RelocsNext = SortedRelocations.begin(); + auto RelocsEnd = SortedRelocations.end(); + auto RelocLess = [](const WasmRelocation &R, uint32_t Val) { + return R.Offset < Val; + }; + for (InputChunk *C : SortedChunks) { + auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd, + C->getInputSectionOffset(), RelocLess); + RelocsNext = std::lower_bound(RelocsStart, RelocsEnd, + C->getInputSectionOffset() + C->getSize(), + RelocLess); + C->copyRelocations(ArrayRef(RelocsStart, RelocsNext)); + } +} + void ObjFile::initializeSymbols() { Symbols.reserve(WasmObj->getNumberOfSymbols()); @@ -237,17 +279,17 @@ for (const WasmSegment &S : WasmObj->dataSegments()) { InputSegment *Seg = make(S, this); - Seg->copyRelocations(*DataSection); Segments.emplace_back(Seg); } + copyRelocations(Segments, DataSection); for (size_t I = 0; I < Funcs.size(); ++I) { const WasmFunction &Func = Funcs[I]; const WasmSignature &Sig = Types[FuncTypes[I]]; InputFunction *F = make(Sig, &Func, this); - F->copyRelocations(*CodeSection); Functions.emplace_back(F); } + copyRelocations(Functions, CodeSection); // Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols // in the object