|
21 | 21 | #include "lld/Common/Strings.h"
|
22 | 22 | #include "lld/Common/Threads.h"
|
23 | 23 | #include "llvm/ADT/DenseSet.h"
|
| 24 | +#include "llvm/ADT/SmallVector.h" |
24 | 25 | #include "llvm/ADT/StringMap.h"
|
25 | 26 | #include "llvm/BinaryFormat/Wasm.h"
|
26 | 27 | #include "llvm/Object/WasmTraits.h"
|
@@ -95,6 +96,7 @@ class Writer {
|
95 | 96 | void createRelocSections();
|
96 | 97 | void createLinkingSection();
|
97 | 98 | void createNameSection();
|
| 99 | + void createProducersSection(); |
98 | 100 |
|
99 | 101 | void writeHeader();
|
100 | 102 | void writeSections();
|
@@ -327,7 +329,8 @@ void Writer::calculateCustomSections() {
|
327 | 329 | StringRef Name = Section->getName();
|
328 | 330 | // These custom sections are known the linker and synthesized rather than
|
329 | 331 | // blindly copied
|
330 |
| - if (Name == "linking" || Name == "name" || Name.startswith("reloc.")) |
| 332 | + if (Name == "linking" || Name == "name" || Name == "producers" || |
| 333 | + Name.startswith("reloc.")) |
331 | 334 | continue;
|
332 | 335 | // .. or it is a debug section
|
333 | 336 | if (StripDebug && Name.startswith(".debug_"))
|
@@ -633,6 +636,45 @@ void Writer::createNameSection() {
|
633 | 636 | Sub.writeTo(Section->getStream());
|
634 | 637 | }
|
635 | 638 |
|
| 639 | +void Writer::createProducersSection() { |
| 640 | + SmallVector<std::pair<std::string, std::string>, 8> Languages; |
| 641 | + SmallVector<std::pair<std::string, std::string>, 8> Tools; |
| 642 | + SmallVector<std::pair<std::string, std::string>, 8> SDKs; |
| 643 | + for (ObjFile *File : Symtab->ObjectFiles) { |
| 644 | + const WasmProducerInfo &Info = File->getWasmObj()->getProducerInfo(); |
| 645 | + for (auto &Producers : {std::make_pair(&Info.Languages, &Languages), |
| 646 | + std::make_pair(&Info.Tools, &Tools), |
| 647 | + std::make_pair(&Info.SDKs, &SDKs)}) |
| 648 | + for (auto &Producer : *Producers.first) |
| 649 | + if (Producers.second->end() == |
| 650 | + std::find_if(Producers.second->begin(), Producers.second->end(), |
| 651 | + [&](std::pair<std::string, std::string> Seen) { |
| 652 | + return Seen.first == Producer.first; |
| 653 | + })) |
| 654 | + Producers.second->push_back(Producer); |
| 655 | + } |
| 656 | + int FieldCount = |
| 657 | + int(!Languages.empty()) + int(!Tools.empty()) + int(!SDKs.empty()); |
| 658 | + if (FieldCount == 0) |
| 659 | + return; |
| 660 | + SyntheticSection *Section = |
| 661 | + createSyntheticSection(WASM_SEC_CUSTOM, "producers"); |
| 662 | + auto &OS = Section->getStream(); |
| 663 | + writeUleb128(OS, FieldCount, "field count"); |
| 664 | + for (auto &Field : |
| 665 | + {std::make_pair("language", Languages), |
| 666 | + std::make_pair("processed-by", Tools), std::make_pair("sdk", SDKs)}) { |
| 667 | + if (Field.second.empty()) |
| 668 | + continue; |
| 669 | + writeStr(OS, Field.first, "field name"); |
| 670 | + writeUleb128(OS, Field.second.size(), "number of entries"); |
| 671 | + for (auto &Entry : Field.second) { |
| 672 | + writeStr(OS, Entry.first, "producer name"); |
| 673 | + writeStr(OS, Entry.second, "producer version"); |
| 674 | + } |
| 675 | + } |
| 676 | +} |
| 677 | + |
636 | 678 | void Writer::writeHeader() {
|
637 | 679 | memcpy(Buffer->getBufferStart(), Header.data(), Header.size());
|
638 | 680 | }
|
@@ -772,9 +814,13 @@ void Writer::createSections() {
|
772 | 814 | createLinkingSection();
|
773 | 815 | createRelocSections();
|
774 | 816 | }
|
| 817 | + |
775 | 818 | if (!Config->StripDebug && !Config->StripAll)
|
776 | 819 | createNameSection();
|
777 | 820 |
|
| 821 | + if (!Config->StripAll) |
| 822 | + createProducersSection(); |
| 823 | + |
778 | 824 | for (OutputSection *S : OutputSections) {
|
779 | 825 | S->setOffset(FileSize);
|
780 | 826 | S->finalizeContents();
|
|
0 commit comments