Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -99,6 +99,7 @@ const WasmSection *CodeSection = nullptr; const WasmSection *DataSection = nullptr; + const WasmSection *ProducersSection = nullptr; // Maps input type indices to output type indices std::vector TypeMap; @@ -139,7 +140,7 @@ }; // Will report a fatal() error if the input buffer is not a valid bitcode -// or was object file. +// or wasm object file. InputFile *createObjectFile(MemoryBufferRef MB); // Opens a given file. Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -240,6 +240,8 @@ CustomSections.emplace_back(make(Section, this)); CustomSections.back()->setRelocations(Section.Relocations); CustomSectionsByIndex[SectionIndex] = CustomSections.back(); + if (Section.Name == "producers") + ProducersSection = &Section; } SectionIndex++; } Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -21,6 +21,8 @@ #include "lld/Common/Strings.h" #include "lld/Common/Threads.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/BinaryFormat/Wasm.h" #include "llvm/Object/WasmTraits.h" @@ -95,6 +97,7 @@ void createRelocSections(); void createLinkingSection(); void createNameSection(); + void createProducersSection(); void writeHeader(); void writeSections(); @@ -327,7 +330,8 @@ StringRef Name = Section->getName(); // These custom sections are known the linker and synthesized rather than // blindly copied - if (Name == "linking" || Name == "name" || Name.startswith("reloc.")) + if (Name == "linking" || Name == "name" || Name == "producers" || + Name.startswith("reloc.")) continue; // .. or it is a debug section if (StripDebug && Name.startswith(".debug_")) @@ -633,6 +637,45 @@ Sub.writeTo(Section->getStream()); } +void Writer::createProducersSection() { + SmallVector, 8> Languages; + SmallVector, 8> Tools; + SmallVector, 8> SDKs; + for (ObjFile *File : Symtab->ObjectFiles) { + const WasmProducerInfo &Info = File->getWasmObj()->getProducerInfo(); + for (auto &Producers : {std::make_pair(&Info.Languages, &Languages), + std::make_pair(&Info.Tools, &Tools), + std::make_pair(&Info.SDKs, &SDKs)}) { + llvm::SmallSet SeenProducers; + for (auto &Producer : *Producers.first) { + if (SeenProducers.insert(Producer.first).second) { + Producers.second->push_back(Producer); + } + } + } + } + int Fields = + int(!Languages.empty()) + int(!Tools.empty()) + int(!SDKs.empty()); + if (Fields == 0) + return; + SyntheticSection *Section = + createSyntheticSection(WASM_SEC_CUSTOM, "producers"); + auto &OS = Section->getStream(); + writeUleb128(OS, Fields, "field count"); + for (auto &Field : {std::make_pair(StringRef("language"), Languages), + std::make_pair(StringRef("processed-by"), Tools), + std::make_pair(StringRef("sdk"), SDKs)}) { + if (Field.second.empty()) + continue; + writeStr(OS, Field.first, "field name"); + writeUleb128(OS, Field.second.size(), "number of entries"); + for (auto &Entry : Field.second) { + writeStr(OS, Entry.first, "producer name"); + writeStr(OS, Entry.second, "producer version"); + } + } +} + void Writer::writeHeader() { memcpy(Buffer->getBufferStart(), Header.data(), Header.size()); } @@ -775,6 +818,9 @@ if (!Config->StripDebug && !Config->StripAll) createNameSection(); + if (!Config->StripAll) + createProducersSection(); + for (OutputSection *S : OutputSections) { S->setOffset(FileSize); S->finalizeContents();