summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/WasmObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/WasmObjectWriter.cpp')
-rw-r--r--llvm/lib/MC/WasmObjectWriter.cpp189
1 files changed, 164 insertions, 25 deletions
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 0e122708504..88bd046ec6e 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -48,7 +48,9 @@ static const uint32_t kInitialTableOffset = 1;
struct SectionBookkeeping {
// Where the size of the section is written.
uint64_t SizeOffset;
- // Where the contents of the section starts (after the header).
+ // Where the section header ends (without custom section name).
+ uint64_t PayloadOffset;
+ // Where the contents of the section starts.
uint64_t ContentsOffset;
uint32_t Index;
};
@@ -151,6 +153,8 @@ struct WasmRelocationEntry {
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
return true;
default:
return false;
@@ -169,11 +173,17 @@ struct WasmRelocationEntry {
};
struct WasmCustomSection {
+ const uint32_t INVALID_INDEX = -1;
+
StringRef Name;
- const SmallVectorImpl<char> &Contents;
+ MCSectionWasm *Section;
+
+ uint32_t OutputContentsOffset;
+ uint32_t OutputIndex;
- WasmCustomSection(StringRef Name, const SmallVectorImpl<char> &Contents)
- : Name(Name), Contents(Contents) {}
+ WasmCustomSection(StringRef Name, MCSectionWasm *Section)
+ : Name(Name), Section(Section), OutputContentsOffset(0),
+ OutputIndex(INVALID_INDEX) {}
};
#if !defined(NDEBUG)
@@ -207,13 +217,21 @@ class WasmObjectWriter : public MCObjectWriter {
DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
// Maps data symbols to the Wasm segment and offset/size with the segment.
DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
+ // Maps section symbols to the section.
+ DenseMap<const MCSymbolWasm *, const MCSectionWasm *> CustomSectionSymbols;
+
+ // Stores output data (index, relocations, content offset) for custom
+ // section.
+ std::vector<WasmCustomSection> CustomSections;
+ // Relocations for fixing up references in the custom sections.
+ DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
+ CustomSectionsRelocations;
DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
FunctionTypeIndices;
SmallVector<WasmFunctionType, 4> FunctionTypes;
SmallVector<WasmGlobal, 4> Globals;
SmallVector<WasmDataSegment, 4> DataSegments;
- std::vector<WasmCustomSection> CustomSections;
unsigned NumFunctionImports = 0;
unsigned NumGlobalImports = 0;
uint32_t SectionCount = 0;
@@ -245,10 +263,12 @@ private:
WasmIndices.clear();
TableIndices.clear();
DataLocations.clear();
+ CustomSectionsRelocations.clear();
FunctionTypeIndices.clear();
FunctionTypes.clear();
Globals.clear();
DataSegments.clear();
+ CustomSectionSymbols.clear();
MCObjectWriter::reset();
NumFunctionImports = 0;
NumGlobalImports = 0;
@@ -290,7 +310,11 @@ private:
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
- void writeUserCustomSections(ArrayRef<WasmCustomSection> CustomSections);
+ void writeCustomSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ void writeCustomRelocSections();
+ void
+ updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions,
+ const MCAsmLayout &Layout);
uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
@@ -319,6 +343,7 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section,
// The position where the section starts, for measuring its size.
Section.ContentsOffset = getStream().tell();
+ Section.PayloadOffset = getStream().tell();
Section.Index = SectionCount++;
}
@@ -326,14 +351,21 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
StringRef Name) {
DEBUG(dbgs() << "startCustomSection " << Name << "\n");
startSection(Section, wasm::WASM_SEC_CUSTOM);
+
+ // The position where the section header ends, for measuring its size.
+ Section.PayloadOffset = getStream().tell();
+
// Custom sections in wasm also have a string identifier.
writeString(Name);
+
+ // The position where the custom section starts.
+ Section.ContentsOffset = getStream().tell();
}
// Now that the section is complete and we know how big it is, patch up the
// section size field at the start of the section.
void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
- uint64_t Size = getStream().tell() - Section.ContentsOffset;
+ uint64_t Size = getStream().tell() - Section.PayloadOffset;
if (uint32_t(Size) != Size)
report_fatal_error("section size does not fit in a uint32_t");
@@ -374,8 +406,9 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
if (FixupSection.getSectionName().startswith(".init_array"))
return;
- // TODO(sbc): Add support for debug sections.
- if (FixupSection.getKind().isMetadata())
+ // TODO: Add support for non-debug metadata sections?
+ if (FixupSection.getKind().isMetadata() &&
+ !FixupSection.getSectionName().startswith(".debug_"))
return;
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
@@ -446,21 +479,29 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
- // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB are currently required
- // to be against a named symbol.
+ // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB,
+ // R_WEBASSEMBLY_SECTION_OFFSET_I32 or R_WEBASSEMBLY_FUNCTION_OFFSET_I32
+ // are currently required to be against a named symbol.
// TODO(sbc): Add support for relocations against unnamed temporaries such
// as those generated by llvm's `blockaddress`.
// See: test/MC/WebAssembly/blockaddress.ll
- if (SymA->getName().empty() && Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
+ if (SymA->getName().empty() &&
+ !(Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB ||
+ Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 ||
+ Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32))
report_fatal_error("relocations against un-named temporaries are not yet "
"supported by wasm");
- if (FixupSection.isWasmData())
+ if (FixupSection.isWasmData()) {
DataRelocations.push_back(Rec);
- else if (FixupSection.getKind().isText())
+ } else if (FixupSection.getKind().isText()) {
CodeRelocations.push_back(Rec);
- else
+ } else if (FixupSection.getKind().isMetadata()) {
+ assert(FixupSection.getSectionName().startswith(".debug_"));
+ CustomSectionsRelocations[&FixupSection].push_back(Rec);
+ } else {
llvm_unreachable("unexpected section type");
+ }
}
// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
@@ -523,6 +564,15 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
report_fatal_error("symbol not found in wasm index space: " +
RelEntry.Symbol->getName());
return WasmIndices[RelEntry.Symbol];
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: {
+ const auto &Section =
+ static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
+ return Section.getSectionOffset() + RelEntry.Addend;
+ }
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: {
+ const auto &Section = *CustomSectionSymbols.find(RelEntry.Symbol)->second;
+ return Section.getSectionOffset() + RelEntry.Addend;
+ }
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
@@ -614,6 +664,8 @@ void WasmObjectWriter::applyRelocations(
break;
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
WriteI32(Stream, Value, Offset);
break;
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
@@ -851,6 +903,13 @@ void WasmObjectWriter::writeRelocSection(
endSection(Section);
}
+void WasmObjectWriter::writeCustomRelocSections() {
+ for (const auto &Sec : CustomSections) {
+ auto &Relocations = CustomSectionsRelocations[Sec.Section];
+ writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
+ }
+}
+
void WasmObjectWriter::writeLinkingMetaDataSection(
ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
@@ -881,6 +940,12 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
encodeULEB128(Sym.DataRef.Size, getStream());
}
break;
+ case wasm::WASM_SYMBOL_TYPE_SECTION: {
+ const uint32_t SectionIndex =
+ CustomSections[Sym.ElementIndex].OutputIndex;
+ encodeULEB128(SectionIndex, getStream());
+ break;
+ }
default:
llvm_unreachable("unexpected kind");
}
@@ -927,16 +992,66 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
endSection(Section);
}
-void WasmObjectWriter::writeUserCustomSections(
- ArrayRef<WasmCustomSection> CustomSections) {
- for (const auto &CustomSection : CustomSections) {
+void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ for (auto &CustomSection : CustomSections) {
SectionBookkeeping Section;
+ auto *Sec = CustomSection.Section;
startCustomSection(Section, CustomSection.Name);
- writeBytes(CustomSection.Contents);
+
+ Sec->setSectionOffset(getStream().tell() - Section.ContentsOffset);
+ Asm.writeSectionData(Sec, Layout);
+
+ CustomSection.OutputContentsOffset = Section.ContentsOffset;
+ CustomSection.OutputIndex = Section.Index;
+
endSection(Section);
}
}
+void WasmObjectWriter::updateCustomSectionRelocations(
+ const SmallVector<WasmFunction, 4> &Functions, const MCAsmLayout &Layout) {
+ std::map<const MCSection *, const MCSymbolWasm *> SectionSymbols;
+ for (const auto &P : CustomSectionSymbols)
+ SectionSymbols[P.second] = P.first;
+ std::map<const MCSection *, const MCSymbolWasm *> FuncSymbols;
+ for (const auto &FuncInfo : Functions)
+ FuncSymbols[&FuncInfo.Sym->getSection()] = FuncInfo.Sym;
+
+ // Patch relocation records for R_WEBASSEMBLY_FUNCTION_OFFSET_I32 and
+ // R_WEBASSEMBLY_SECTION_OFFSET_I32. The Addend is stuffed the offset from
+ // the beginning of the function or custom section -- all such relocations
+ // target the function or custom section starts.
+ for (auto &Section : CustomSections) {
+ auto &Relocations = CustomSectionsRelocations[Section.Section];
+ for (WasmRelocationEntry &RelEntry : Relocations) {
+ switch (RelEntry.Type) {
+ case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: {
+ assert(RelEntry.hasAddend());
+ auto &Section =
+ static_cast<MCSectionWasm &>(RelEntry.Symbol->getSection());
+ RelEntry.Addend += Layout.getSymbolOffset(*RelEntry.Symbol);
+ RelEntry.Symbol = FuncSymbols[&Section];
+ break;
+ }
+ case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: {
+ assert(RelEntry.hasAddend());
+ auto &Section =
+ static_cast<MCSectionWasm &>(RelEntry.Symbol->getSection());
+ RelEntry.Addend += Layout.getSymbolOffset(*RelEntry.Symbol);
+ RelEntry.Symbol = SectionSymbols[&Section];
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Apply fixups.
+ applyRelocations(Relocations, Section.OutputContentsOffset);
+ }
+}
+
uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
assert(Symbol.isFunction());
assert(TypeIndices.count(&Symbol));
@@ -1043,8 +1158,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
for (MCSection &Sec : Asm) {
auto &Section = static_cast<MCSectionWasm &>(Sec);
- if (cast<MCSectionWasm>(Sec).getSectionName().startswith(
- ".custom_section.")) {
+ if (Section.getSectionName().startswith(".custom_section.")) {
if (Section.getFragmentList().empty())
continue;
if (Section.getFragmentList().size() != 1)
@@ -1057,8 +1171,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
if (!DataFrag.getFixups().empty())
report_fatal_error("fixups not supported in .custom_section section");
StringRef UserName = Section.getSectionName().substr(16);
- const SmallVectorImpl<char> &Contents = DataFrag.getContents();
- CustomSections.push_back(WasmCustomSection(UserName, Contents));
+ CustomSections.emplace_back(UserName, &Section);
continue;
}
@@ -1088,6 +1201,31 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
}
+ // Create symbols for debug/custom sections.
+ for (MCSection &Sec : Asm) {
+ auto &DebugSection = static_cast<MCSectionWasm &>(Sec);
+ StringRef SectionName = DebugSection.getSectionName();
+
+ // TODO: Add support for non-debug metadata sections?
+ if (!Sec.getKind().isMetadata() || !SectionName.startswith(".debug_"))
+ continue;
+
+ uint32_t ElementIndex = CustomSections.size();
+ CustomSections.emplace_back(SectionName, &DebugSection);
+
+ MCSymbolWasm *SectionSym =
+ cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SectionName));
+ CustomSectionSymbols[SectionSym] = &DebugSection;
+
+ wasm::WasmSymbolInfo Info;
+ Info.Name = SectionSym->getName();
+ Info.Kind = wasm::WASM_SYMBOL_TYPE_SECTION;
+ Info.Flags = 0;
+ Info.ElementIndex = ElementIndex;
+ SymbolIndices[SectionSym] = SymbolInfos.size();
+ SymbolInfos.emplace_back(Info);
+ }
+
// Populate WasmIndices and DataLocations for defined symbols.
for (const MCSymbol &S : Asm.symbols()) {
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
@@ -1331,13 +1469,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeElemSection(TableElems);
writeCodeSection(Asm, Layout, Functions);
writeDataSection();
- writeUserCustomSections(CustomSections);
+ writeCustomSections(Asm, Layout);
+ updateCustomSectionRelocations(Functions, Layout);
writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
+ writeCustomRelocSections();
// TODO: Translate the .comment section to the output.
- // TODO: Translate debug sections to the output.
}
std::unique_ptr<MCObjectWriter>
OpenPOWER on IntegriCloud