diff options
| author | Sam Clegg <sbc@chromium.org> | 2018-08-22 17:27:31 +0000 |
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2018-08-22 17:27:31 +0000 |
| commit | f77dc2a8d1d7bdd433d04ba2386d860f31a4f358 (patch) | |
| tree | 466d7eff31ce266626c7f368b000ed53fc6dd4d2 | |
| parent | 4fc7e6a1e95e022f9f42c6a616f21828e65f68b1 (diff) | |
| download | bcm5719-llvm-f77dc2a8d1d7bdd433d04ba2386d860f31a4f358.tar.gz bcm5719-llvm-f77dc2a8d1d7bdd433d04ba2386d860f31a4f358.zip | |
[WebAssembly] Ensure relocation entries are ordered by offset
wasm-lld expects relocation entries to be sorted by offset. In most
cases llvm produces them in order, but the CODE section (which combines
many MCSections) is an exception because we order the functions in
Symbol order, not in section order. What is more, its not clear weather
`recordRelocation` is guaranteed to be called in offset order so this
sort of most likely needed in the general case too.
Differential Revision: https://reviews.llvm.org/D51065
llvm-svn: 340423
| -rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/Object/WasmObjectFile.cpp | 5 |
2 files changed, 22 insertions, 5 deletions
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 5a979d36e81..f6c5a874e7c 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -306,7 +306,7 @@ private: ArrayRef<WasmFunction> Functions); void writeDataSection(); void writeRelocSection(uint32_t SectionIndex, StringRef Name, - ArrayRef<WasmRelocationEntry> Relocations); + std::vector<WasmRelocationEntry>& Relocations); void writeLinkingMetaDataSection( ArrayRef<wasm::WasmSymbolInfo> SymbolInfos, ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs, @@ -892,19 +892,31 @@ void WasmObjectWriter::writeDataSection() { void WasmObjectWriter::writeRelocSection( uint32_t SectionIndex, StringRef Name, - ArrayRef<WasmRelocationEntry> Relocations) { + std::vector<WasmRelocationEntry>& Relocs) { // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md // for descriptions of the reloc sections. - if (Relocations.empty()) + if (Relocs.empty()) return; + // First, ensure the relocations are sorted in offset order. In general they + // should already be sorted since `recordRelocation` is called in offset + // order, but for the code section we combine many MC sections into single + // wasm section, and this order is determined by the order of Asm.Symbols() + // not the sections order. + std::stable_sort( + Relocs.begin(), Relocs.end(), + [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) { + return (A.Offset + A.FixupSection->getSectionOffset()) < + (B.Offset + B.FixupSection->getSectionOffset()); + }); + SectionBookkeeping Section; startCustomSection(Section, std::string("reloc.") + Name.str()); encodeULEB128(SectionIndex, W.OS); - encodeULEB128(Relocations.size(), W.OS); - for (const WasmRelocationEntry& RelEntry : Relocations) { + encodeULEB128(Relocs.size(), W.OS); + for (const WasmRelocationEntry& RelEntry : Relocs) { uint64_t Offset = RelEntry.Offset + RelEntry.FixupSection->getSectionOffset(); uint32_t Index = getRelocationIndexValue(RelEntry); diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 1b32ae8afd9..f75dbfc3014 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -602,10 +602,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { WasmSection& Section = Sections[SectionIndex]; uint32_t RelocCount = readVaruint32(Ctx); uint32_t EndOffset = Section.Content.size(); + uint32_t PreviousOffset = 0; while (RelocCount--) { wasm::WasmRelocation Reloc = {}; Reloc.Type = readVaruint32(Ctx); Reloc.Offset = readVaruint32(Ctx); + if (Reloc.Offset < PreviousOffset) + return make_error<GenericBinaryError>("Relocations not in offset order", + object_error::parse_failed); + PreviousOffset = Reloc.Offset; Reloc.Index = readVaruint32(Ctx); switch (Reloc.Type) { case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |

