Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -184,6 +184,9 @@ // Relocations for fixing up references in the data section. std::vector DataRelocations; + // Relocations for fixing up references in the debug sections. + std::vector DebugRelocations; + // Index values to use for fixing up call_indirect type indices. // Maps function symbols to the index of the type of the function DenseMap TypeIndices; @@ -227,6 +230,7 @@ void reset() override { CodeRelocations.clear(); DataRelocations.clear(); + DebugRelocations.clear(); TypeIndices.clear(); SymbolIndices.clear(); WasmIndices.clear(); @@ -273,11 +277,13 @@ void writeDataSection(); void writeCodeRelocSection(); void writeDataRelocSection(); + void writeDebugRelocSection(const MCAsmLayout &Layout); void writeLinkingMetaDataSection( ArrayRef SymbolInfos, ArrayRef> InitFuncs, const std::map> &Comdats); + void writeDebugSections(const MCAssembler &Asm, const MCAsmLayout &Layout); uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry); void applyRelocations(ArrayRef Relocations, uint64_t ContentsOffset); @@ -362,9 +368,11 @@ if (FixupSection.getSectionName().startswith(".init_array")) return; - // TODO(sbc): Add support for debug sections. - if (FixupSection.getKind().isMetadata()) - return; + // TODO: Add support for non-debug metadata sections? + if (FixupSection.getKind().isMetadata()) { + if (!FixupSection.getSectionName().startswith(".debug_")) + return; + } if (const MCSymbolRefExpr *RefB = Target.getSymB()) { assert(RefB->getKind() == MCSymbolRefExpr::VK_None && @@ -439,7 +447,9 @@ // 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 && + (!FixupSection.getKind().isMetadata() || Type != wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32))) report_fatal_error("relocations against un-named temporaries are not yet " "supported by wasm"); @@ -447,6 +457,8 @@ DataRelocations.push_back(Rec); else if (FixupSection.getKind().isText()) CodeRelocations.push_back(Rec); + else if (FixupSection.getKind().isMetadata()) + DebugRelocations.push_back(Rec); else llvm_unreachable("unexpected section type"); } @@ -861,6 +873,60 @@ endSection(Section); } +void WasmObjectWriter::writeDebugRelocSection(const MCAsmLayout &Layout) { + if (DebugRelocations.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DEBUG"); + + encodeULEB128(DebugRelocations.size(), getStream()); + + // Write all entries in following format: + // type ULEB128 = R_WEBASSEMBLY_MEMORY_ADDR_I32 + // fixup section code (+maybe custom section name) + // fixup offset + // target section code (+maybe name) + // target + // addend + // TODO: It is possible to have running table of section codes to compress + // custom name, e.g. have an index in the table instead of code + name, and + // if it's out of table bounds append table with following code + name. + raw_pwrite_stream &Stream = getStream(); + for (const WasmRelocationEntry& RelEntry : DebugRelocations) { + + auto WriteSectionCode = [&] (const MCSectionWasm& Section) { + if (Section.isWasmData()) { + encodeULEB128(wasm::WASM_SEC_DATA, Stream); + } else if (Section.getKind().isText()) { + encodeULEB128(wasm::WASM_SEC_CODE, Stream); + } else if (Section.getSectionName().startswith(".debug_")) { + encodeULEB128(wasm::WASM_SEC_CUSTOM, Stream); + writeString(Section.getSectionName().str()); + } else + llvm_unreachable("unexpected section type/kind"); + }; + + assert(RelEntry.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32); + + uint64_t Offset = RelEntry.Offset + RelEntry.FixupSection->getSectionOffset(); + + auto& TargetSection = static_cast(RelEntry.Symbol->getSection()); + uint32_t TargetOffset = Layout.getSymbolOffset(*RelEntry.Symbol) + + TargetSection.getSectionOffset(); + + write8(RelEntry.Type); + WriteSectionCode(*RelEntry.FixupSection); + encodeULEB128(Offset, Stream); + WriteSectionCode(TargetSection); + encodeULEB128(TargetOffset, Stream); + if (RelEntry.hasAddend()) + encodeSLEB128(RelEntry.Addend, Stream); + } + + endSection(Section); +} + void WasmObjectWriter::writeLinkingMetaDataSection( ArrayRef SymbolInfos, ArrayRef> InitFuncs, @@ -936,6 +1002,26 @@ endSection(Section); } +void WasmObjectWriter::writeDebugSections(const MCAssembler &Asm, const MCAsmLayout &Layout) { + for (MCSection &Sec : Asm) { + auto &DebugSection = static_cast(Sec); + StringRef SectionName = DebugSection.getSectionName(); + if (!SectionName.startswith(".debug_")) { + continue; + } + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_CUSTOM, SectionName.str().c_str()); + + DebugSection.setSectionOffset(getStream().tell() - Section.ContentsOffset); + Asm.writeSectionData(&DebugSection, Layout); + + endSection(Section); + + //writeDebugSection(Asm, DebugSection, Layout); + } +} + uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) { assert(Symbol.isFunction()); assert(TypeIndices.count(&Symbol)); @@ -1307,12 +1393,13 @@ writeElemSection(TableElems); writeCodeSection(Asm, Layout, Functions); writeDataSection(); + writeDebugSections(Asm, Layout); writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); writeCodeRelocSection(); writeDataRelocSection(); + writeDebugRelocSection(Layout); // TODO: Translate the .comment section to the output. - // TODO: Translate debug sections to the output. } std::unique_ptr